Spaces:
Running
Running
kartikmandar
commited on
Commit
·
79a213a
1
Parent(s):
8d0cf27
ui bug fixed
Browse files- assets/icons/svg.py +10 -0
- assets/images/holoviz_logo.png +0 -0
- assets/images/holoviz_logo_minimised.png +0 -0
- assets/images/stingray_explorer_minimised.png +0 -0
- assets/images/stingray_logo_minimised.png +0 -0
- explorer.py +19 -10
- modules/DataLoading/DataIngestion.py +124 -0
- modules/Home/HomeContent.py +27 -21
- modules/QuickLook/LightCurve.py +6 -6
- utils/dashboardClasses.py +18 -8
- utils/sidebar.py +22 -11
- utils/strings.py +144 -3
assets/icons/svg.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# These are the icons for the sidebar buttons
|
2 |
+
|
3 |
+
HOME_ICON_SVG = """
|
4 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-home"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 12l-2 0l9 -9l9 9l-2 0" /><path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" /><path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6" /></svg>
|
5 |
+
"""
|
6 |
+
|
7 |
+
LOAD_DATA_ICON_SVG = """
|
8 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-file-upload"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M14 3v4a1 1 0 0 0 1 1h4" /><path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" /><path d="M12 11v6" /><path d="M9.5 13.5l2.5 -2.5l2.5 2.5" /></svg>
|
9 |
+
"""
|
10 |
+
|
assets/images/holoviz_logo.png
ADDED
assets/images/holoviz_logo_minimised.png
ADDED
assets/images/stingray_explorer_minimised.png
ADDED
assets/images/stingray_logo_minimised.png
ADDED
explorer.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
import panel as pn
|
2 |
-
from utils.strings import HOME_HEADING_STRING, WELCOME_MESSAGE_STRING, FOOTER_STRING
|
3 |
from modules.Home.HomeContent import create_home_bokeh_plots_container, create_home_footer, create_home_header, create_home_help_box, create_home_main_area, create_home_output_box, create_home_warning_box
|
4 |
from utils.sidebar import create_sidebar
|
5 |
|
@@ -25,7 +24,7 @@ output_box = create_home_output_box()
|
|
25 |
warning_box = create_home_warning_box()
|
26 |
|
27 |
# Create the plots container
|
28 |
-
|
29 |
|
30 |
# Create the help box
|
31 |
help_box = create_home_help_box()
|
@@ -33,7 +32,16 @@ help_box = create_home_help_box()
|
|
33 |
# Create the footer
|
34 |
footer = create_home_footer()
|
35 |
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
|
39 |
# Create a FastGridTemplate layout
|
@@ -64,7 +72,7 @@ layout = pn.template.FastGridTemplate(
|
|
64 |
theme_toggle=True,
|
65 |
# background_color="#FFFFFF", # The toggle button choses it according to the theme
|
66 |
neutral_color="#D3D3D3",
|
67 |
-
accent_base_color="#
|
68 |
header_background="#000000",
|
69 |
header_color="#c4e1c5",
|
70 |
header_neutral_color="#D3D3D3",
|
@@ -88,13 +96,14 @@ layout = pn.template.FastGridTemplate(
|
|
88 |
base_target="_self",
|
89 |
)
|
90 |
|
91 |
-
layout.main[0:10, 0:12] =
|
92 |
-
layout.main[10:45, 0:8] =
|
93 |
-
layout.main[10:
|
94 |
-
layout.main[
|
95 |
layout.main[45:85, 0:12] = bokeh_plots_container
|
96 |
-
layout.main[85:120, 0:12] =
|
97 |
-
layout.main[120:150, 0:12] =
|
|
|
98 |
|
99 |
# Serve the layout
|
100 |
layout.servable()
|
|
|
1 |
import panel as pn
|
|
|
2 |
from modules.Home.HomeContent import create_home_bokeh_plots_container, create_home_footer, create_home_header, create_home_help_box, create_home_main_area, create_home_output_box, create_home_warning_box
|
3 |
from utils.sidebar import create_sidebar
|
4 |
|
|
|
24 |
warning_box = create_home_warning_box()
|
25 |
|
26 |
# Create the plots container
|
27 |
+
bokeh_plots = create_home_bokeh_plots_container()
|
28 |
|
29 |
# Create the help box
|
30 |
help_box = create_home_help_box()
|
|
|
32 |
# Create the footer
|
33 |
footer = create_home_footer()
|
34 |
|
35 |
+
# Containers for changing the layouts dynamically
|
36 |
+
header_container = pn.Column(header)
|
37 |
+
main_area_container = pn.Column(main_area)
|
38 |
+
output_box_container = pn.Column(output_box)
|
39 |
+
warning_box_container = pn.Column(warning_box)
|
40 |
+
bokeh_plots_container = pn.Column(bokeh_plots)
|
41 |
+
help_box_container = pn.Column(help_box)
|
42 |
+
footer_container = pn.Column(footer)
|
43 |
+
|
44 |
+
sidebar = create_sidebar(main_area=main_area_container, header=header_container, footer=footer_container, output_box=output_box_container, warning_box=warning_box_container, help_box=help_box_container)
|
45 |
|
46 |
|
47 |
# Create a FastGridTemplate layout
|
|
|
72 |
theme_toggle=True,
|
73 |
# background_color="#FFFFFF", # The toggle button choses it according to the theme
|
74 |
neutral_color="#D3D3D3",
|
75 |
+
accent_base_color="#5ead61",
|
76 |
header_background="#000000",
|
77 |
header_color="#c4e1c5",
|
78 |
header_neutral_color="#D3D3D3",
|
|
|
96 |
base_target="_self",
|
97 |
)
|
98 |
|
99 |
+
layout.main[0:10, 0:12] = header_container
|
100 |
+
layout.main[10:45, 0:8] = main_area_container
|
101 |
+
layout.main[10:27, 8:12] = output_box_container
|
102 |
+
layout.main[27:45, 8:12] = warning_box_container
|
103 |
layout.main[45:85, 0:12] = bokeh_plots_container
|
104 |
+
layout.main[85:120, 0:12] = help_box_container
|
105 |
+
layout.main[120:150, 0:12] = footer_container
|
106 |
+
|
107 |
|
108 |
# Serve the layout
|
109 |
layout.servable()
|
modules/DataLoading/DataIngestion.py
CHANGED
@@ -103,3 +103,127 @@ async def load_event_data(
|
|
103 |
# Clear the warnings after displaying them
|
104 |
warning_handler.warnings.clear()
|
105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
# Clear the warnings after displaying them
|
104 |
warning_handler.warnings.clear()
|
105 |
|
106 |
+
def save_loaded_files(
|
107 |
+
event, filename_input, format_input, format_checkbox, output, warning_output
|
108 |
+
):
|
109 |
+
if not loaded_event_data:
|
110 |
+
output.value = "No files loaded to save."
|
111 |
+
return
|
112 |
+
|
113 |
+
filenames = (
|
114 |
+
[name.strip() for name in filename_input.value.split(",")]
|
115 |
+
if filename_input.value
|
116 |
+
else [event[0] for event in loaded_event_data]
|
117 |
+
)
|
118 |
+
formats = (
|
119 |
+
[fmt.strip() for fmt in format_input.value.split(",")]
|
120 |
+
if format_input.value
|
121 |
+
else []
|
122 |
+
)
|
123 |
+
|
124 |
+
if format_checkbox.value:
|
125 |
+
formats = ["hdf5" for _ in range(len(loaded_event_data))]
|
126 |
+
|
127 |
+
if len(filenames) < len(loaded_event_data):
|
128 |
+
output.value = "Please specify names for all loaded files."
|
129 |
+
return
|
130 |
+
if len(filenames) != len(loaded_event_data):
|
131 |
+
output.value = (
|
132 |
+
"Please ensure that the number of names matches the number of loaded files."
|
133 |
+
)
|
134 |
+
return
|
135 |
+
if len(formats) < len(loaded_event_data):
|
136 |
+
output.value = "Please specify formats for all loaded files or check the default format option."
|
137 |
+
return
|
138 |
+
|
139 |
+
saved_files = []
|
140 |
+
try:
|
141 |
+
for (loaded_name, event_list), file_name, file_format in zip(
|
142 |
+
loaded_event_data, filenames, formats
|
143 |
+
):
|
144 |
+
if os.path.exists(
|
145 |
+
os.path.join(loaded_data_path, f"{file_name}.{file_format}")
|
146 |
+
):
|
147 |
+
output.value = f"A file with the name '{file_name}' already exists. Please provide a different name."
|
148 |
+
return
|
149 |
+
|
150 |
+
save_path = os.path.join(loaded_data_path, f"{file_name}.{file_format}")
|
151 |
+
if file_format == 'hdf5':
|
152 |
+
event_list.to_astropy_table().write(save_path, format=file_format, path='data')
|
153 |
+
else:
|
154 |
+
event_list.write(save_path, file_format)
|
155 |
+
|
156 |
+
saved_files.append(
|
157 |
+
f"File '{file_name}' saved successfully to '{save_path}'."
|
158 |
+
)
|
159 |
+
|
160 |
+
output.value = "\n".join(saved_files)
|
161 |
+
if warning_handler.warnings:
|
162 |
+
warning_output.value = "\n".join(warning_handler.warnings)
|
163 |
+
else:
|
164 |
+
warning_output.value = "No warnings."
|
165 |
+
except Exception as e:
|
166 |
+
output.value = f"An error occurred while saving files: {e}"
|
167 |
+
|
168 |
+
# Clear the warnings after displaying them
|
169 |
+
warning_handler.warnings.clear()
|
170 |
+
|
171 |
+
|
172 |
+
|
173 |
+
def delete_selected_files(event, file_selector, output, warning_output):
|
174 |
+
if not file_selector.value:
|
175 |
+
output.value = "No file selected. Please select a file to delete."
|
176 |
+
return
|
177 |
+
|
178 |
+
file_paths = file_selector.value
|
179 |
+
deleted_files = []
|
180 |
+
for file_path in file_paths:
|
181 |
+
if file_path.endswith(".py"):
|
182 |
+
deleted_files.append(
|
183 |
+
f"Cannot delete file '{file_path}': Deleting .py files is not allowed."
|
184 |
+
)
|
185 |
+
continue
|
186 |
+
|
187 |
+
try:
|
188 |
+
# Change the file permissions to ensure it can be deleted
|
189 |
+
os.chmod(file_path, stat.S_IWUSR | stat.S_IREAD | stat.S_IWRITE)
|
190 |
+
os.remove(file_path)
|
191 |
+
deleted_files.append(f"File '{file_path}' deleted successfully.")
|
192 |
+
except Exception as e:
|
193 |
+
deleted_files.append(f"An error occurred while deleting '{file_path}': {e}")
|
194 |
+
|
195 |
+
output.value = "\n".join(deleted_files)
|
196 |
+
if warning_handler.warnings:
|
197 |
+
warning_output.value = "\n".join(warning_handler.warnings)
|
198 |
+
else:
|
199 |
+
warning_output.value = "No warnings."
|
200 |
+
|
201 |
+
warning_handler.warnings.clear()
|
202 |
+
|
203 |
+
|
204 |
+
def preview_loaded_files(event, output, warning_output, time_limit=10):
|
205 |
+
if not loaded_event_data:
|
206 |
+
output.value = "No files loaded to preview."
|
207 |
+
return
|
208 |
+
|
209 |
+
preview_data = []
|
210 |
+
for file_name, event_list in loaded_event_data:
|
211 |
+
try:
|
212 |
+
time_data = f"Times (first {time_limit}): {event_list.time[:time_limit]}"
|
213 |
+
mjdref = f"MJDREF: {event_list.mjdref}"
|
214 |
+
gti = f"GTI: {event_list.gti}"
|
215 |
+
preview_data.append(f"File: {file_name}\n{time_data}\n{mjdref}\n{gti}\n")
|
216 |
+
except Exception as e:
|
217 |
+
warning_handler.warn(str(e), category=RuntimeWarning)
|
218 |
+
|
219 |
+
if preview_data:
|
220 |
+
output.value = "\n\n".join(preview_data)
|
221 |
+
else:
|
222 |
+
output.value = "No valid files loaded for preview."
|
223 |
+
|
224 |
+
if warning_handler.warnings:
|
225 |
+
warning_output.value = "\n".join(warning_handler.warnings)
|
226 |
+
else:
|
227 |
+
warning_output.value = "No warnings."
|
228 |
+
|
229 |
+
warning_handler.warnings.clear()
|
modules/Home/HomeContent.py
CHANGED
@@ -1,42 +1,48 @@
|
|
1 |
# homecontent.py
|
2 |
|
3 |
import panel as pn
|
4 |
-
from utils.
|
5 |
from bokeh.plotting import figure
|
|
|
6 |
|
7 |
def create_home_header():
|
8 |
home_heading_input = pn.widgets.TextInput(name="Heading", value="Welcome to Stingray Explorer")
|
9 |
-
home_subheading_input = pn.widgets.TextInput(name="Subheading", value="
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
def create_home_main_area():
|
13 |
-
tab1_content = pn.pane.Markdown(
|
14 |
-
tab2_content = pn.pane.
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
tabs_content = {"hi": tab1_content, "Tab 2": tab2_content, "Tab 3": tab3_content, "Tab 4": tab4_content, "alflakj": tab3_content}
|
21 |
return MainArea(tabs_content=tabs_content)
|
22 |
|
23 |
def create_home_output_box():
|
24 |
-
return OutputBox(output_content=
|
25 |
|
26 |
def create_home_warning_box():
|
27 |
-
return WarningBox(warning_content=
|
28 |
|
29 |
def create_home_bokeh_plots_container():
|
30 |
-
p1 =
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
return BokehPlotsContainer(flexbox_contents=[p1, p2, p3], titles=["Scatter Plot", "Line Plot", "Bar Plot"], sizes=[(200, 200), (200, 200), (300, 300)])
|
37 |
|
38 |
def create_home_help_box():
|
39 |
-
help_content =
|
40 |
return HelpBox(help_content=help_content, title="Help Section")
|
41 |
|
42 |
def create_home_footer():
|
|
|
1 |
# homecontent.py
|
2 |
|
3 |
import panel as pn
|
4 |
+
from utils.DashboardClasses import MainHeader, MainArea, OutputBox, WarningBox, BokehPlotsContainer, HelpBox, Footer
|
5 |
from bokeh.plotting import figure
|
6 |
+
from utils.strings import HOME_HEADER_STRING, WELCOME_MESSAGE_STRING, FOOTER_STRING, STINGRAY_TAB_STRING, HOLOVIZ_TAB_STRING, DASHBOARD_TAB_STRING, OUTPUT_BOX_STRING, WARNING_BOX_STRING, HELP_BOX_STRING
|
7 |
|
8 |
def create_home_header():
|
9 |
home_heading_input = pn.widgets.TextInput(name="Heading", value="Welcome to Stingray Explorer")
|
10 |
+
home_subheading_input = pn.widgets.TextInput(name="Subheading", value="Stingray GUI using HoloViz")
|
11 |
+
|
12 |
+
button = pn.widgets.Button(name="Change Heading", button_type="primary")
|
13 |
+
def change_heading(event):
|
14 |
+
home_heading_input.value = "New Heading"
|
15 |
+
home_subheading_input.value = "New Subheading"
|
16 |
+
button.on_click(change_heading)
|
17 |
+
|
18 |
+
|
19 |
+
return MainHeader(heading=home_heading_input, subheading=home_subheading_input, button_1_name="button", button_1_action=change_heading)
|
20 |
|
21 |
def create_home_main_area():
|
22 |
+
tab1_content = pn.pane.Markdown(STINGRAY_TAB_STRING)
|
23 |
+
tab2_content = pn.pane.Markdown(HOLOVIZ_TAB_STRING)
|
24 |
+
tab3_content = pn.pane.Markdown(DASHBOARD_TAB_STRING)
|
25 |
+
|
26 |
+
tabs_content = {"What's Stingray?": tab1_content, "What's HoloViz?": tab2_content, "Dashboard": tab3_content}
|
27 |
+
|
|
|
|
|
28 |
return MainArea(tabs_content=tabs_content)
|
29 |
|
30 |
def create_home_output_box():
|
31 |
+
return OutputBox(output_content=OUTPUT_BOX_STRING)
|
32 |
|
33 |
def create_home_warning_box():
|
34 |
+
return WarningBox(warning_content=WARNING_BOX_STRING)
|
35 |
|
36 |
def create_home_bokeh_plots_container():
|
37 |
+
p1 = pn.pane.Markdown(" Plot 1")
|
38 |
+
p2 = pn.pane.Markdown(" Plot 2")
|
39 |
+
p3 = pn.pane.Markdown(" Plot 3")
|
40 |
+
p4 = pn.pane.Markdown("Plot 4")
|
41 |
+
p5 = pn.pane.Markdown("Plot 5")
|
42 |
+
return BokehPlotsContainer(flexbox_contents=[p1, p2, p3, p4, p5], titles=["Heading 1", "Heading 2", "Heading 3", "Heading 4", "Heading 5"], sizes=[(300, 300), (300, 300), (300, 300), (300, 300), (300, 300)])
|
|
|
43 |
|
44 |
def create_home_help_box():
|
45 |
+
help_content = HELP_BOX_STRING
|
46 |
return HelpBox(help_content=help_content, title="Help Section")
|
47 |
|
48 |
def create_home_footer():
|
modules/QuickLook/LightCurve.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
import panel as pn
|
2 |
|
3 |
-
from utils.
|
4 |
|
5 |
-
# Create a text input widget for the header
|
6 |
-
heading_input = pn.widgets.TextInput(
|
7 |
-
name="Heading", value="QuickLook Light Curve"
|
8 |
-
)
|
9 |
|
10 |
-
|
|
|
|
|
|
|
|
|
11 |
|
|
|
1 |
import panel as pn
|
2 |
|
3 |
+
from utils.DashboardClasses import MainHeader, MainArea, OutputBox, WarningBox, BokehPlotsContainer, HelpBox, Footer
|
4 |
|
|
|
|
|
|
|
|
|
5 |
|
6 |
+
def create_quicklook_lightcurve_header():
|
7 |
+
# Create a text input widget for the header
|
8 |
+
heading_input = pn.widgets.TextInput(
|
9 |
+
name="Heading", value="QuickLook Light Curve")
|
10 |
+
return MainHeader(heading = heading_input)
|
11 |
|
utils/dashboardClasses.py
CHANGED
@@ -223,9 +223,14 @@ class MainHeader(pn.viewable.Viewer):
|
|
223 |
)
|
224 |
)
|
225 |
|
|
|
|
|
|
|
|
|
|
|
226 |
# Create the layout for the header
|
227 |
layout = pn.Row(
|
228 |
-
pn.Column(
|
229 |
pn.FlexBox(
|
230 |
*buttons,
|
231 |
align_items="center",
|
@@ -235,6 +240,8 @@ class MainHeader(pn.viewable.Viewer):
|
|
235 |
)
|
236 |
|
237 |
return layout
|
|
|
|
|
238 |
|
239 |
|
240 |
class MainArea(pn.viewable.Viewer):
|
@@ -259,7 +266,7 @@ class MainArea(pn.viewable.Viewer):
|
|
259 |
"""
|
260 |
Returns the Panel layout for the main area, which includes tabs with their respective content.
|
261 |
"""
|
262 |
-
tabs = pn.Tabs()
|
263 |
for tab_name, content in self.tabs_content.items():
|
264 |
tabs.append((tab_name, content))
|
265 |
|
@@ -292,7 +299,7 @@ class OutputBox(pn.viewable.Viewer):
|
|
292 |
"""
|
293 |
Returns the Panel layout for the output box, including a heading and the content.
|
294 |
"""
|
295 |
-
heading = pn.pane.Markdown("
|
296 |
output_box = pn.widgets.TextAreaInput(
|
297 |
name="",
|
298 |
value=self.output_content,
|
@@ -303,6 +310,7 @@ class OutputBox(pn.viewable.Viewer):
|
|
303 |
return pn.Column(heading, output_box, sizing_mode="stretch_both")
|
304 |
|
305 |
|
|
|
306 |
class WarningBox(pn.viewable.Viewer):
|
307 |
"""
|
308 |
WarningBox class represents a box to display warning content.
|
@@ -323,7 +331,7 @@ class WarningBox(pn.viewable.Viewer):
|
|
323 |
"""
|
324 |
Returns the Panel layout for the warning box, including a heading and the content.
|
325 |
"""
|
326 |
-
heading = pn.pane.Markdown("
|
327 |
warning_box = pn.widgets.TextAreaInput(
|
328 |
name="",
|
329 |
value=self.warning_content,
|
@@ -372,7 +380,7 @@ class BokehPlotsContainer(pn.viewable.Viewer):
|
|
372 |
else:
|
373 |
title = f"FlexBox {idx+1}"
|
374 |
|
375 |
-
heading = pn.pane.Markdown(f"
|
376 |
flexbox = pn.Column(
|
377 |
heading,
|
378 |
content,
|
@@ -414,7 +422,7 @@ class HelpBox(pn.viewable.Viewer):
|
|
414 |
"""
|
415 |
Returns the Panel layout for the help box, including a heading and Markdown content.
|
416 |
"""
|
417 |
-
heading = pn.pane.Markdown(f"
|
418 |
help_markdown = pn.pane.Markdown(self.help_content, sizing_mode="stretch_both")
|
419 |
return pn.Column(heading, help_markdown, sizing_mode="stretch_both")
|
420 |
|
@@ -479,8 +487,8 @@ class Footer(pn.viewable.Viewer):
|
|
479 |
)
|
480 |
|
481 |
contact_us_pane = pn.FlexBox(
|
482 |
-
pn.pane.Markdown("Email:
|
483 |
-
pn.pane.Markdown("
|
484 |
flex_direction="row",
|
485 |
justify_content="center",
|
486 |
align_items="center",
|
@@ -525,3 +533,5 @@ class Footer(pn.viewable.Viewer):
|
|
525 |
)
|
526 |
|
527 |
return footer
|
|
|
|
|
|
223 |
)
|
224 |
)
|
225 |
|
226 |
+
# Create the layout for the header
|
227 |
+
layout_items = [heading_pane]
|
228 |
+
if self.subheading and self.subheading != "Default Subheading":
|
229 |
+
layout_items.append(subheading_pane)
|
230 |
+
|
231 |
# Create the layout for the header
|
232 |
layout = pn.Row(
|
233 |
+
pn.Column(*layout_items),
|
234 |
pn.FlexBox(
|
235 |
*buttons,
|
236 |
align_items="center",
|
|
|
240 |
)
|
241 |
|
242 |
return layout
|
243 |
+
|
244 |
+
|
245 |
|
246 |
|
247 |
class MainArea(pn.viewable.Viewer):
|
|
|
266 |
"""
|
267 |
Returns the Panel layout for the main area, which includes tabs with their respective content.
|
268 |
"""
|
269 |
+
tabs = pn.Tabs(dynamic=True)
|
270 |
for tab_name, content in self.tabs_content.items():
|
271 |
tabs.append((tab_name, content))
|
272 |
|
|
|
299 |
"""
|
300 |
Returns the Panel layout for the output box, including a heading and the content.
|
301 |
"""
|
302 |
+
heading = pn.pane.Markdown("<h2> Output </h2>")
|
303 |
output_box = pn.widgets.TextAreaInput(
|
304 |
name="",
|
305 |
value=self.output_content,
|
|
|
310 |
return pn.Column(heading, output_box, sizing_mode="stretch_both")
|
311 |
|
312 |
|
313 |
+
|
314 |
class WarningBox(pn.viewable.Viewer):
|
315 |
"""
|
316 |
WarningBox class represents a box to display warning content.
|
|
|
331 |
"""
|
332 |
Returns the Panel layout for the warning box, including a heading and the content.
|
333 |
"""
|
334 |
+
heading = pn.pane.Markdown("<h2> Warning</h2>")
|
335 |
warning_box = pn.widgets.TextAreaInput(
|
336 |
name="",
|
337 |
value=self.warning_content,
|
|
|
380 |
else:
|
381 |
title = f"FlexBox {idx+1}"
|
382 |
|
383 |
+
heading = pn.pane.Markdown(f"<h2> {title} </h2>", align="center")
|
384 |
flexbox = pn.Column(
|
385 |
heading,
|
386 |
content,
|
|
|
422 |
"""
|
423 |
Returns the Panel layout for the help box, including a heading and Markdown content.
|
424 |
"""
|
425 |
+
heading = pn.pane.Markdown(f"<h2> {self.title}</h2>")
|
426 |
help_markdown = pn.pane.Markdown(self.help_content, sizing_mode="stretch_both")
|
427 |
return pn.Column(heading, help_markdown, sizing_mode="stretch_both")
|
428 |
|
|
|
487 |
)
|
488 |
|
489 |
contact_us_pane = pn.FlexBox(
|
490 |
+
pn.pane.Markdown("Email: kartik4321mandar@gmail.com"),
|
491 |
+
pn.pane.Markdown("Slack: @kartikmandar"),
|
492 |
flex_direction="row",
|
493 |
justify_content="center",
|
494 |
align_items="center",
|
|
|
533 |
)
|
534 |
|
535 |
return footer
|
536 |
+
|
537 |
+
|
utils/sidebar.py
CHANGED
@@ -1,23 +1,26 @@
|
|
1 |
import panel as pn
|
2 |
import importlib
|
3 |
-
from modules.QuickLook.LightCurve import
|
4 |
from modules.Home.HomeContent import create_home_bokeh_plots_container, create_home_footer, create_home_header, create_home_help_box, create_home_main_area, create_home_output_box, create_home_warning_box
|
|
|
5 |
|
6 |
def create_sidebar(main_area, header, footer, output_box, warning_box, help_box):
|
7 |
menu_items_quicklook_stingray = [
|
8 |
("Light Curve", "QuickLookLightCurve"),
|
9 |
("Power spectra", "QuickLookPowerspectra"),
|
10 |
-
("
|
11 |
]
|
12 |
|
|
|
13 |
# Home Button
|
14 |
home_button = pn.widgets.Button(
|
15 |
-
name="
|
16 |
)
|
17 |
|
18 |
# Load Button
|
19 |
load_data_button = pn.widgets.Button(
|
20 |
-
name="Load Data", button_type="warning", styles={"width": "100
|
|
|
21 |
)
|
22 |
|
23 |
# Create MenuButtons
|
@@ -25,32 +28,40 @@ def create_sidebar(main_area, header, footer, output_box, warning_box, help_box)
|
|
25 |
name="Quicklook",
|
26 |
items=menu_items_quicklook_stingray,
|
27 |
button_type="primary",
|
28 |
-
styles={"width": "
|
29 |
)
|
30 |
|
31 |
def handle_home_button_selection(event):
|
32 |
-
|
33 |
-
|
34 |
home_button.on_click(handle_home_button_selection)
|
35 |
|
36 |
# Load Button changing main content
|
37 |
def load_data(event):
|
38 |
pass
|
|
|
39 |
load_data_button.on_click(load_data)
|
40 |
|
41 |
# Quicklook Button changing main content
|
42 |
def handle_quicklook_button_selection(event):
|
43 |
clicked = event.new
|
44 |
if clicked == "QuickLookLightCurve":
|
45 |
-
header
|
|
|
46 |
|
47 |
quicklook_stingray_button.on_click(handle_quicklook_button_selection)
|
48 |
|
49 |
-
sidebar = pn.
|
|
|
50 |
pn.pane.Markdown("# Navigation"),
|
51 |
-
home_button,
|
52 |
-
load_data_button,
|
|
|
53 |
quicklook_stingray_button,
|
|
|
|
|
|
|
|
|
54 |
)
|
55 |
|
56 |
return sidebar
|
|
|
1 |
import panel as pn
|
2 |
import importlib
|
3 |
+
from modules.QuickLook.LightCurve import create_quicklook_lightcurve_header
|
4 |
from modules.Home.HomeContent import create_home_bokeh_plots_container, create_home_footer, create_home_header, create_home_help_box, create_home_main_area, create_home_output_box, create_home_warning_box
|
5 |
+
from assets.icons.svg import HOME_ICON_SVG, LOAD_DATA_ICON_SVG
|
6 |
|
7 |
def create_sidebar(main_area, header, footer, output_box, warning_box, help_box):
|
8 |
menu_items_quicklook_stingray = [
|
9 |
("Light Curve", "QuickLookLightCurve"),
|
10 |
("Power spectra", "QuickLookPowerspectra"),
|
11 |
+
("Cross Correlation", "QuickLookCrossCorrelation"),
|
12 |
]
|
13 |
|
14 |
+
|
15 |
# Home Button
|
16 |
home_button = pn.widgets.Button(
|
17 |
+
icon=HOME_ICON_SVG, icon_size="20px", name="", button_type="default", styles={"width": "50"}, description="Back to Home"
|
18 |
)
|
19 |
|
20 |
# Load Button
|
21 |
load_data_button = pn.widgets.Button(
|
22 |
+
icon=LOAD_DATA_ICON_SVG, icon_size="20px",name="Load Data", button_type="warning", styles={"width": "100"},
|
23 |
+
description="Loading EventList"
|
24 |
)
|
25 |
|
26 |
# Create MenuButtons
|
|
|
28 |
name="Quicklook",
|
29 |
items=menu_items_quicklook_stingray,
|
30 |
button_type="primary",
|
31 |
+
styles={"width": "90%"},
|
32 |
)
|
33 |
|
34 |
def handle_home_button_selection(event):
|
35 |
+
header[:]=[create_home_header()]
|
36 |
+
|
37 |
home_button.on_click(handle_home_button_selection)
|
38 |
|
39 |
# Load Button changing main content
|
40 |
def load_data(event):
|
41 |
pass
|
42 |
+
|
43 |
load_data_button.on_click(load_data)
|
44 |
|
45 |
# Quicklook Button changing main content
|
46 |
def handle_quicklook_button_selection(event):
|
47 |
clicked = event.new
|
48 |
if clicked == "QuickLookLightCurve":
|
49 |
+
header[:]=[create_quicklook_lightcurve_header()]
|
50 |
+
|
51 |
|
52 |
quicklook_stingray_button.on_click(handle_quicklook_button_selection)
|
53 |
|
54 |
+
sidebar = pn.FlexBox(
|
55 |
+
|
56 |
pn.pane.Markdown("# Navigation"),
|
57 |
+
pn.FlexBox(home_button,
|
58 |
+
load_data_button, flex_direction="row", justify_content="center", align_items="center"),
|
59 |
+
|
60 |
quicklook_stingray_button,
|
61 |
+
|
62 |
+
flex_direction="column",
|
63 |
+
align_items="flex-start",
|
64 |
+
justify_content="flex-start",
|
65 |
)
|
66 |
|
67 |
return sidebar
|
utils/strings.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
-
## This section contains the textual strings used in the
|
2 |
|
3 |
-
|
4 |
<h1>Welcome to the Stingray Explorer Dashboard</h1>
|
5 |
"""
|
6 |
|
@@ -68,4 +68,145 @@ FOOTER_STRING = """
|
|
68 |
<p>Stingray Explorer Dashboard</p>
|
69 |
<p>© 2021 Kartik Mandar</p>
|
70 |
</div>
|
71 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## This section contains the textual strings used in the HomeContent.py
|
2 |
|
3 |
+
HOME_HEADER_STRING = """
|
4 |
<h1>Welcome to the Stingray Explorer Dashboard</h1>
|
5 |
"""
|
6 |
|
|
|
68 |
<p>Stingray Explorer Dashboard</p>
|
69 |
<p>© 2021 Kartik Mandar</p>
|
70 |
</div>
|
71 |
+
"""
|
72 |
+
|
73 |
+
|
74 |
+
# Tabs in Main Area of Home Page
|
75 |
+
|
76 |
+
STINGRAY_TAB_STRING = """
|
77 |
+
<h2> Stingray: Next-Generation Spectral Timing </h2>
|
78 |
+
|
79 |
+
![Stingray-logo](../assets/images/stingray_logo_minimised.png)
|
80 |
+
|
81 |
+
Stingray is a Python library designed to perform time series analysis and related tasks on astronomical light curves. It supports a range of commonly-used Fourier analysis techniques, as well as extensions for analyzing pulsar data, simulating data sets, and statistical modeling. Stingray is designed to be easy to extend and easy to incorporate into data analysis workflows and pipelines.
|
82 |
+
|
83 |
+
<h3> Features </h3>
|
84 |
+
|
85 |
+
<h4> Current Capabilities </h4>
|
86 |
+
|
87 |
+
1. **Data handling and simulation**
|
88 |
+
- Loading event lists from FITS files (and generally good handling of OGIP-compliant missions, like RXTE/PCA, NuSTAR/FPM, XMM-Newton/EPIC, NICER/XTI)
|
89 |
+
- Constructing light curves and time series from event data
|
90 |
+
- Various operations on time series (e.g. addition, subtraction, joining, and truncation)
|
91 |
+
- Simulating a light curve with a given power spectrum
|
92 |
+
- Simulating a light curve from another light curve and a 1-d (time) or 2-d (time-energy) impulse response
|
93 |
+
- Simulating an event list from a given light curve _and_ with a given energy spectrum
|
94 |
+
- Good Time Interval operations
|
95 |
+
- Filling gaps in light curves with statistically sound fake data
|
96 |
+
|
97 |
+
2. **Fourier methods**
|
98 |
+
- Power spectra and cross spectra in Leahy, rms normalization, absolute rms, and no normalization
|
99 |
+
- Averaged power spectra and cross spectra
|
100 |
+
- Dynamical power spectra and cross spectra
|
101 |
+
- Maximum likelihood fitting of periodograms/parametric models
|
102 |
+
- (Averaged) cross spectra
|
103 |
+
- Coherence, time lags
|
104 |
+
- Variability-Energy spectra, like covariance spectra and lags (needs testing)
|
105 |
+
- Covariance spectra (needs testing)
|
106 |
+
- Bispectra (needs testing)
|
107 |
+
- (Bayesian) quasi-periodic oscillation searches
|
108 |
+
- Lomb-Scargle periodograms and cross spectra
|
109 |
+
- Power Colors
|
110 |
+
|
111 |
+
3. **Other time series methods**
|
112 |
+
- Pulsar searches with Epoch Folding, Z-test
|
113 |
+
- Gaussian Processes for QPO studies
|
114 |
+
- Cross-correlation functions
|
115 |
+
|
116 |
+
<h4> Future Plans </h4>
|
117 |
+
|
118 |
+
Other future additions we are currently implementing are:
|
119 |
+
- Bicoherence
|
120 |
+
- Phase-resolved spectroscopy of quasi-periodic oscillations
|
121 |
+
- Fourier-frequency-resolved spectroscopy
|
122 |
+
- Full HEASARC-compatible mission support
|
123 |
+
- Pulsar searches with Z-test
|
124 |
+
- Binary pulsar searches
|
125 |
+
|
126 |
+
<h4> Platform-specific Issues </h4>
|
127 |
+
|
128 |
+
Windows uses an internal 32-bit representation for int. This might create numerical errors when using large integer numbers (e.g., when calculating the sum of a light curve, if the lc.counts array is an integer). On Windows, we automatically convert the counts array to float. The small numerical errors should be a relatively small issue compared to the above.
|
129 |
+
|
130 |
+
<br></br>
|
131 |
+
"""
|
132 |
+
|
133 |
+
HOLOVIZ_TAB_STRING = """
|
134 |
+
<h2> High-level tools to simplify visualization in Python </h2>
|
135 |
+
|
136 |
+
![HoloViz-logo](../assets/images/holoviz_logo_minimised.png)
|
137 |
+
|
138 |
+
**HoloViz provides:**
|
139 |
+
|
140 |
+
- High-level tools that make it easier to apply Python plotting libraries to your data.
|
141 |
+
- A comprehensive tutorial showing how to use the available tools together to do a wide range of different tasks.
|
142 |
+
- Sample datasets to work with.
|
143 |
+
|
144 |
+
<h3> HoloViz-maintained libraries </h3>
|
145 |
+
|
146 |
+
HoloViz provides a set of Python packages that make visualization easier, more accurate, and more powerful:
|
147 |
+
|
148 |
+
- **Panel**: For making apps and dashboards for your plots from any supported plotting library.
|
149 |
+
- **hvPlot**: To quickly generate interactive plots from your data.
|
150 |
+
- **HoloViews**: To help you make all of your data instantly visualizable.
|
151 |
+
- **GeoViews**: To extend HoloViews for geographic data.
|
152 |
+
- **Datashader**: For rendering even the largest datasets.
|
153 |
+
- **Lumen**: To build data-driven dashboards from a simple YAML specification.
|
154 |
+
- **Param**: To create declarative user-configurable objects.
|
155 |
+
- **Colorcet**: For perceptually uniform colormaps.
|
156 |
+
|
157 |
+
<h3> Building on the SciPy/PyData/PyViz ecosystem </h3>
|
158 |
+
|
159 |
+
HoloViz tools build on the many excellent visualization tools available in the scientific Python ecosystem, allowing you to access their power conveniently and efficiently. The core tools make use of:
|
160 |
+
- **Bokeh**: For interactive plotting.
|
161 |
+
- **Matplotlib**: For publication-quality output.
|
162 |
+
- **Plotly**: For interactive 3D visualizations.
|
163 |
+
|
164 |
+
**Panel** lets you combine any of these visualizations with output from nearly any other Python plotting library, including specific support for:
|
165 |
+
- seaborn
|
166 |
+
- altair
|
167 |
+
- vega
|
168 |
+
- plotnine
|
169 |
+
- graphviz
|
170 |
+
- ggplot2
|
171 |
+
- Plus anything that can generate HTML, PNG, or SVG.
|
172 |
+
|
173 |
+
HoloViz tools and examples generally work with any Python standard data types (lists, dictionaries, etc.), plus:
|
174 |
+
- Pandas or Dask DataFrames
|
175 |
+
- NumPy, Xarray, or Dask arrays
|
176 |
+
- Including remote data from the Intake data catalog library.
|
177 |
+
|
178 |
+
They also use Dask and Numba to speed up computations along with algorithms and functions from SciPy, and support both GPUs and CPUs to make use of all your available hardware.
|
179 |
+
|
180 |
+
HoloViz tools are designed for general-purpose use but also support some domain-specific datatypes like:
|
181 |
+
- Graphs from NetworkX
|
182 |
+
- Geographic data from GeoPandas, Cartopy, and Iris.
|
183 |
+
|
184 |
+
HoloViz tools provide extensive support for Jupyter notebooks, as well as for standalone Python-backed web servers and exporting visualizations or apps as images or static HTML files.
|
185 |
+
<br/>
|
186 |
+
"""
|
187 |
+
|
188 |
+
DASHBOARD_TAB_STRING = """
|
189 |
+
<h2> Stingray Explorer </h2>
|
190 |
+
|
191 |
+
![Stingray-Explorer-logo](../assets/images/stingray_explorer_minimised.png)
|
192 |
+
|
193 |
+
This dashboard is designed to provide a comprehensive toolset for X-ray astronomy data analysis. For now the dashboard provided quicklook features like generating an EventList, loading an EvenList, and generating a lightcurve from the EventList.
|
194 |
+
|
195 |
+
<br/>
|
196 |
+
"""
|
197 |
+
|
198 |
+
OUTPUT_BOX_STRING = """
|
199 |
+
This is the output container. It will display the output of the analysis tools.
|
200 |
+
It may contain what EventLists are made, what lightcurves are generated, what power spectra are calculated, etc. It can also be used to preview the loaded EventList.
|
201 |
+
"""
|
202 |
+
|
203 |
+
|
204 |
+
WARNING_BOX_STRING = """
|
205 |
+
This is the warning container. It will display any warnings or errors that occur during the analysis process.
|
206 |
+
"""
|
207 |
+
|
208 |
+
HELP_BOX_STRING = """
|
209 |
+
This is the helpbox container. It will display any help or documentation for the analysis tools.
|
210 |
+
It will also have links to the documentation and tutorials for the tools.
|
211 |
+
And have a brief description of the physics behind the analysis.
|
212 |
+
"""
|