Spaces:
Running
Running
Commit ·
4e5bb12
1
Parent(s): 615125c
add docstrings and comments in explorer.py
Browse files- explorer.py +45 -14
- modules/QuickLook/EventList.py +104 -85
explorer.py
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import panel as pn
|
| 2 |
import holoviews as hv
|
| 3 |
from modules.Home.HomeContent import (
|
|
@@ -14,44 +33,44 @@ from modules.Home.HomeContent import (
|
|
| 14 |
from utils.sidebar import create_sidebar
|
| 15 |
|
| 16 |
|
| 17 |
-
# Initialize
|
| 18 |
pn.extension('floatpanel', 'mathjax')
|
| 19 |
pn.extension('filedropper')
|
| 20 |
pn.extension('echarts')
|
| 21 |
pn.extension(nthreads=0)
|
| 22 |
hv.extension('bokeh')
|
| 23 |
|
| 24 |
-
# Create a boolean status indicator
|
| 25 |
busy_indicator = pn.indicators.BooleanStatus(
|
| 26 |
value=True, color="warning", width=30, height=30
|
| 27 |
)
|
| 28 |
|
| 29 |
-
# Create the header
|
| 30 |
header = create_home_header()
|
| 31 |
|
| 32 |
-
# Create resource monitor
|
| 33 |
resource_monitor = create_home_resource_monitor()
|
| 34 |
|
| 35 |
-
# Create the main area
|
| 36 |
main_area = create_home_main_area()
|
| 37 |
|
| 38 |
-
# Create the output
|
| 39 |
output_box = create_home_output_box()
|
| 40 |
|
| 41 |
-
# Create the warning box
|
| 42 |
warning_box = create_home_warning_box()
|
| 43 |
|
| 44 |
-
# Create the help box
|
| 45 |
help_box = create_home_help_area()
|
| 46 |
|
| 47 |
-
# Create the footer
|
| 48 |
footer = create_home_footer()
|
| 49 |
|
| 50 |
-
#
|
| 51 |
plots_area = create_home_plots_area_initial()
|
| 52 |
|
| 53 |
|
| 54 |
-
#
|
| 55 |
header_container = pn.Column(header)
|
| 56 |
resource_monitor_container = pn.Column(resource_monitor)
|
| 57 |
main_area_container = pn.Column(main_area)
|
|
@@ -62,9 +81,10 @@ help_box_container = pn.Column(help_box)
|
|
| 62 |
footer_container = pn.Column(footer)
|
| 63 |
float_panel_container = pn.Column(pn.pane.Markdown("This is not a bug that this container is scrolling, it's a container to hold Floating Plots. You can ignore it completely."))
|
| 64 |
|
| 65 |
-
# Floating
|
| 66 |
# floating_plot_demo = create_floating_plot_demo(floating_panel_container)
|
| 67 |
|
|
|
|
| 68 |
sidebar = create_sidebar(
|
| 69 |
main_area=main_area_container,
|
| 70 |
resource_usage=resource_monitor_container,
|
|
@@ -78,7 +98,18 @@ sidebar = create_sidebar(
|
|
| 78 |
)
|
| 79 |
|
| 80 |
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
layout = pn.template.FastGridTemplate(
|
| 83 |
# Basic Panel layout components
|
| 84 |
main=[],
|
|
@@ -141,5 +172,5 @@ layout.main[140:170, 0:12] = footer_container
|
|
| 141 |
layout.main[170:170, 0:12] = float_panel_container
|
| 142 |
|
| 143 |
|
| 144 |
-
#
|
| 145 |
layout.servable()
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Stingray Explorer Main Application File
|
| 3 |
+
|
| 4 |
+
This module serves as the entry point for the Stingray Explorer dashboard application.
|
| 5 |
+
It handles the initialization of the Panel/Holoviews environment and sets up the
|
| 6 |
+
dashboard layout and components.
|
| 7 |
+
|
| 8 |
+
The dashboard provides an interactive interface for analyzing X-ray astronomy data
|
| 9 |
+
using the Stingray library, with various visualization and analysis tools.
|
| 10 |
+
|
| 11 |
+
Key Components:
|
| 12 |
+
- Header: Main navigation and branding
|
| 13 |
+
- Sidebar: Control panel for data loading and analysis
|
| 14 |
+
- Main Area: Primary workspace for data visualization
|
| 15 |
+
- Plots Area: Container for generated plots and charts
|
| 16 |
+
- Resource Monitor: System resource usage display
|
| 17 |
+
- Help/Info Sections: Documentation and support resources
|
| 18 |
+
"""
|
| 19 |
+
|
| 20 |
import panel as pn
|
| 21 |
import holoviews as hv
|
| 22 |
from modules.Home.HomeContent import (
|
|
|
|
| 33 |
from utils.sidebar import create_sidebar
|
| 34 |
|
| 35 |
|
| 36 |
+
# Initialize Panel and Holoviews extensions with required features
|
| 37 |
pn.extension('floatpanel', 'mathjax')
|
| 38 |
pn.extension('filedropper')
|
| 39 |
pn.extension('echarts')
|
| 40 |
pn.extension(nthreads=0)
|
| 41 |
hv.extension('bokeh')
|
| 42 |
|
| 43 |
+
# Create a boolean status indicator to show system activity
|
| 44 |
busy_indicator = pn.indicators.BooleanStatus(
|
| 45 |
value=True, color="warning", width=30, height=30
|
| 46 |
)
|
| 47 |
|
| 48 |
+
# Create the main dashboard header with branding and navigation
|
| 49 |
header = create_home_header()
|
| 50 |
|
| 51 |
+
# Create resource monitor to display system usage statistics
|
| 52 |
resource_monitor = create_home_resource_monitor()
|
| 53 |
|
| 54 |
+
# Create the main workspace area for data visualization and analysis
|
| 55 |
main_area = create_home_main_area()
|
| 56 |
|
| 57 |
+
# Create the output console for displaying analysis results and messages
|
| 58 |
output_box = create_home_output_box()
|
| 59 |
|
| 60 |
+
# Create the warning box for displaying important alerts and notifications
|
| 61 |
warning_box = create_home_warning_box()
|
| 62 |
|
| 63 |
+
# Create the help box containing documentation and support resources
|
| 64 |
help_box = create_home_help_area()
|
| 65 |
|
| 66 |
+
# Create the footer with copyright and additional information
|
| 67 |
footer = create_home_footer()
|
| 68 |
|
| 69 |
+
# Create the plots area container for visualization outputs
|
| 70 |
plots_area = create_home_plots_area_initial()
|
| 71 |
|
| 72 |
|
| 73 |
+
# Create containers for each section to enable dynamic layout management
|
| 74 |
header_container = pn.Column(header)
|
| 75 |
resource_monitor_container = pn.Column(resource_monitor)
|
| 76 |
main_area_container = pn.Column(main_area)
|
|
|
|
| 81 |
footer_container = pn.Column(footer)
|
| 82 |
float_panel_container = pn.Column(pn.pane.Markdown("This is not a bug that this container is scrolling, it's a container to hold Floating Plots. You can ignore it completely."))
|
| 83 |
|
| 84 |
+
# Floating plot container for additional visualization options
|
| 85 |
# floating_plot_demo = create_floating_plot_demo(floating_panel_container)
|
| 86 |
|
| 87 |
+
# Create the sidebar with navigation and control elements
|
| 88 |
sidebar = create_sidebar(
|
| 89 |
main_area=main_area_container,
|
| 90 |
resource_usage=resource_monitor_container,
|
|
|
|
| 98 |
)
|
| 99 |
|
| 100 |
|
| 101 |
+
"""
|
| 102 |
+
Create the main dashboard layout using Panel's FastGridTemplate
|
| 103 |
+
|
| 104 |
+
The layout organizes all components into a responsive grid system with:
|
| 105 |
+
- Header at the top
|
| 106 |
+
- Sidebar on the left
|
| 107 |
+
- Main content area in the center
|
| 108 |
+
- Plots and output sections below
|
| 109 |
+
- Footer at the bottom
|
| 110 |
+
|
| 111 |
+
The grid is fully responsive and adapts to different screen sizes.
|
| 112 |
+
"""
|
| 113 |
layout = pn.template.FastGridTemplate(
|
| 114 |
# Basic Panel layout components
|
| 115 |
main=[],
|
|
|
|
| 172 |
layout.main[170:170, 0:12] = float_panel_container
|
| 173 |
|
| 174 |
|
| 175 |
+
# Make the layout available for serving
|
| 176 |
layout.servable()
|
modules/QuickLook/EventList.py
CHANGED
|
@@ -838,17 +838,34 @@ def create_eventlist_operations_tab(
|
|
| 838 |
try:
|
| 839 |
rmf_file = rmf_file_input.value
|
| 840 |
if not rmf_file:
|
| 841 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 842 |
|
| 843 |
if not os.path.isfile(rmf_file):
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
|
|
|
|
|
|
|
|
|
| 847 |
|
| 848 |
# Perform PI to Energy conversion
|
| 849 |
selected_index = selected_indices[0]
|
| 850 |
event_list_name, event_list = loaded_event_data[selected_index]
|
| 851 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 852 |
if rmf_newEventList_checkbox.value:
|
| 853 |
new_event_list = copy.deepcopy(
|
| 854 |
event_list
|
|
@@ -984,9 +1001,12 @@ def create_eventlist_operations_tab(
|
|
| 984 |
try:
|
| 985 |
energy_ranges_input_value = energy_ranges_input.value
|
| 986 |
if not energy_ranges_input_value:
|
| 987 |
-
|
| 988 |
-
|
| 989 |
-
|
|
|
|
|
|
|
|
|
|
| 990 |
try:
|
| 991 |
energy_ranges = eval(energy_ranges_input_value)
|
| 992 |
if (
|
|
@@ -994,14 +1014,20 @@ def create_eventlist_operations_tab(
|
|
| 994 |
or len(energy_ranges) != 2
|
| 995 |
or not all(len(er) == 2 for er in energy_ranges)
|
| 996 |
):
|
| 997 |
-
|
| 998 |
-
|
| 999 |
-
|
|
|
|
|
|
|
|
|
|
| 1000 |
energy_ranges = [[float(x) for x in er] for er in energy_ranges]
|
| 1001 |
except Exception:
|
| 1002 |
-
|
| 1003 |
-
|
| 1004 |
-
|
|
|
|
|
|
|
|
|
|
| 1005 |
|
| 1006 |
segment_size = segment_size_input.value
|
| 1007 |
use_pi = color_use_pi_checkbox.value
|
|
@@ -1337,78 +1363,71 @@ def create_eventlist_operations_tab(
|
|
| 1337 |
),
|
| 1338 |
pn.Column(
|
| 1339 |
pn.FlexBox(
|
| 1340 |
-
|
| 1341 |
-
pn.
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
|
| 1347 |
-
|
| 1348 |
-
|
| 1349 |
-
pn.
|
| 1350 |
-
|
| 1351 |
-
|
| 1352 |
-
|
| 1353 |
-
|
| 1354 |
-
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
|
| 1358 |
-
|
| 1359 |
-
|
| 1360 |
-
|
| 1361 |
-
|
| 1362 |
-
|
| 1363 |
-
|
| 1364 |
-
|
| 1365 |
-
|
| 1366 |
-
|
| 1367 |
-
|
| 1368 |
-
|
| 1369 |
-
|
| 1370 |
-
|
| 1371 |
-
|
| 1372 |
-
|
| 1373 |
-
|
| 1374 |
-
|
| 1375 |
-
|
| 1376 |
-
|
| 1377 |
-
|
| 1378 |
-
|
| 1379 |
-
|
| 1380 |
-
|
| 1381 |
-
|
| 1382 |
-
|
| 1383 |
-
|
| 1384 |
-
|
| 1385 |
-
|
| 1386 |
-
|
| 1387 |
-
|
| 1388 |
-
|
| 1389 |
-
|
| 1390 |
-
|
| 1391 |
-
|
| 1392 |
-
|
| 1393 |
-
|
| 1394 |
-
|
| 1395 |
-
|
| 1396 |
-
|
| 1397 |
-
|
| 1398 |
-
|
| 1399 |
-
|
| 1400 |
-
|
| 1401 |
-
|
| 1402 |
-
|
| 1403 |
-
|
| 1404 |
-
|
| 1405 |
-
pn.pane.Markdown("## Sort EventLists"),
|
| 1406 |
-
sort_inplace_checkbox,
|
| 1407 |
-
sort_button,
|
| 1408 |
-
width=400,
|
| 1409 |
-
height=300,
|
| 1410 |
-
),
|
| 1411 |
-
|
| 1412 |
flex_direction="row",
|
| 1413 |
flex_wrap="wrap",
|
| 1414 |
align_items="center",
|
|
|
|
| 838 |
try:
|
| 839 |
rmf_file = rmf_file_input.value
|
| 840 |
if not rmf_file:
|
| 841 |
+
warning_box_container[:] = [
|
| 842 |
+
create_eventlist_warning_box(
|
| 843 |
+
"Warning: No RMF file provided. Conversion cannot proceed."
|
| 844 |
+
)
|
| 845 |
+
]
|
| 846 |
+
return
|
| 847 |
|
| 848 |
if not os.path.isfile(rmf_file):
|
| 849 |
+
warning_box_container[:] = [
|
| 850 |
+
create_eventlist_warning_box(
|
| 851 |
+
f"Warning: RMF file '{rmf_file}' does not exist. Please provide a valid file path."
|
| 852 |
+
)
|
| 853 |
+
]
|
| 854 |
+
return
|
| 855 |
|
| 856 |
# Perform PI to Energy conversion
|
| 857 |
selected_index = selected_indices[0]
|
| 858 |
event_list_name, event_list = loaded_event_data[selected_index]
|
| 859 |
|
| 860 |
+
# Check if PI data is available
|
| 861 |
+
if not hasattr(event_list, "pi") or event_list.pi is None:
|
| 862 |
+
warning_box_container[:] = [
|
| 863 |
+
create_eventlist_warning_box(
|
| 864 |
+
f"Warning: EventList '{event_list_name}' has no valid PI data. Cannot convert to Energy."
|
| 865 |
+
)
|
| 866 |
+
]
|
| 867 |
+
return
|
| 868 |
+
|
| 869 |
if rmf_newEventList_checkbox.value:
|
| 870 |
new_event_list = copy.deepcopy(
|
| 871 |
event_list
|
|
|
|
| 1001 |
try:
|
| 1002 |
energy_ranges_input_value = energy_ranges_input.value
|
| 1003 |
if not energy_ranges_input_value:
|
| 1004 |
+
warning_box_container[:] = [
|
| 1005 |
+
create_eventlist_warning_box(
|
| 1006 |
+
"Warning: Energy ranges input cannot be empty. Provide two energy ranges as [[min1, max1], [min2, max2]]."
|
| 1007 |
+
)
|
| 1008 |
+
]
|
| 1009 |
+
return
|
| 1010 |
try:
|
| 1011 |
energy_ranges = eval(energy_ranges_input_value)
|
| 1012 |
if (
|
|
|
|
| 1014 |
or len(energy_ranges) != 2
|
| 1015 |
or not all(len(er) == 2 for er in energy_ranges)
|
| 1016 |
):
|
| 1017 |
+
warning_box_container[:] = [
|
| 1018 |
+
create_eventlist_warning_box(
|
| 1019 |
+
"Warning: Invalid energy ranges format. Provide two energy ranges as [[min1, max1], [min2, max2]]."
|
| 1020 |
+
)
|
| 1021 |
+
]
|
| 1022 |
+
return
|
| 1023 |
energy_ranges = [[float(x) for x in er] for er in energy_ranges]
|
| 1024 |
except Exception:
|
| 1025 |
+
warning_box_container[:] = [
|
| 1026 |
+
create_eventlist_warning_box(
|
| 1027 |
+
"Warning: Invalid energy ranges format. Provide two energy ranges as [[min1, max1], [min2, max2]]."
|
| 1028 |
+
)
|
| 1029 |
+
]
|
| 1030 |
+
return
|
| 1031 |
|
| 1032 |
segment_size = segment_size_input.value
|
| 1033 |
use_pi = color_use_pi_checkbox.value
|
|
|
|
| 1363 |
),
|
| 1364 |
pn.Column(
|
| 1365 |
pn.FlexBox(
|
| 1366 |
+
pn.Column(
|
| 1367 |
+
pn.pane.Markdown("## Apply Deadtime"),
|
| 1368 |
+
deadtime_input,
|
| 1369 |
+
deadtime_inplace_checkbox,
|
| 1370 |
+
apply_deadtime_button,
|
| 1371 |
+
width=400,
|
| 1372 |
+
height=300,
|
| 1373 |
+
),
|
| 1374 |
+
pn.Column(
|
| 1375 |
+
pn.pane.Markdown("## Convert PI to Energy"),
|
| 1376 |
+
rmf_file_input,
|
| 1377 |
+
rmf_newEventList_checkbox,
|
| 1378 |
+
convert_pi_button,
|
| 1379 |
+
width=400,
|
| 1380 |
+
height=300,
|
| 1381 |
+
),
|
| 1382 |
+
pn.Column(
|
| 1383 |
+
pn.pane.Markdown("## Filter by Energy Range"),
|
| 1384 |
+
energy_range_input,
|
| 1385 |
+
filterEnergy_inplace_checkbox,
|
| 1386 |
+
filterEnergy_use_pi_checkbox,
|
| 1387 |
+
filter_energy_button,
|
| 1388 |
+
width=400,
|
| 1389 |
+
height=300,
|
| 1390 |
+
),
|
| 1391 |
+
pn.Column(
|
| 1392 |
+
pn.pane.Markdown("## Compute Color Evolution"),
|
| 1393 |
+
energy_ranges_input,
|
| 1394 |
+
segment_size_input,
|
| 1395 |
+
color_use_pi_checkbox,
|
| 1396 |
+
compute_color_button,
|
| 1397 |
+
width=400,
|
| 1398 |
+
height=300,
|
| 1399 |
+
),
|
| 1400 |
+
pn.Column(
|
| 1401 |
+
pn.pane.Markdown("## Get Energy Mask"),
|
| 1402 |
+
energy_mask_input,
|
| 1403 |
+
energy_mask_use_pi_checkbox,
|
| 1404 |
+
get_energy_mask_button,
|
| 1405 |
+
width=400,
|
| 1406 |
+
height=300,
|
| 1407 |
+
),
|
| 1408 |
+
pn.Column(
|
| 1409 |
+
pn.pane.Markdown("## Compute Intensity Evolution"),
|
| 1410 |
+
intensity_energy_range_input,
|
| 1411 |
+
intensity_segment_size_input,
|
| 1412 |
+
intensity_use_pi_checkbox,
|
| 1413 |
+
compute_intensity_button,
|
| 1414 |
+
width=400,
|
| 1415 |
+
height=300,
|
| 1416 |
+
),
|
| 1417 |
+
pn.Column(
|
| 1418 |
+
pn.pane.Markdown("## Join EventLists"),
|
| 1419 |
+
join_strategy_select,
|
| 1420 |
+
join_button,
|
| 1421 |
+
width=400,
|
| 1422 |
+
height=300,
|
| 1423 |
+
),
|
| 1424 |
+
pn.Column(
|
| 1425 |
+
pn.pane.Markdown("## Sort EventLists"),
|
| 1426 |
+
sort_inplace_checkbox,
|
| 1427 |
+
sort_button,
|
| 1428 |
+
width=400,
|
| 1429 |
+
height=300,
|
| 1430 |
+
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1431 |
flex_direction="row",
|
| 1432 |
flex_wrap="wrap",
|
| 1433 |
align_items="center",
|