Spaces:
Running
Running
# Standard Imports | |
import os | |
import numpy as np | |
from matplotlib import pyplot as plt | |
from matplotlib.offsetbox import AnchoredText | |
# HoloViz Imports | |
import panel as pn | |
# Stingray Imports | |
from stingray.events import EventList | |
from stingray.gti import get_gti_lengths, get_btis, get_total_gti_length | |
# Dashboard Classes and Event Data Imports | |
from utils.globals import loaded_event_data | |
from utils.DashboardClasses import ( | |
MainHeader, | |
MainArea, | |
OutputBox, | |
WarningBox, | |
HelpBox, | |
Footer, | |
FloatingPlot, | |
PlotsContainer, | |
) | |
# Strings Imports | |
from utils.strings import ( | |
HOME_HEADER_STRING, | |
HOME_STINGRAY_TAB_STRING, | |
HOME_HOLOVIZ_TAB_STRING, | |
HOME_DASHBOARD_TAB_STRING, | |
HOME_OUTPUT_BOX_STRING, | |
HOME_WARNING_BOX_STRING, | |
HOME_HELP_BOX_STRING, | |
DASHBOARD_HELP_CONTENT, | |
) | |
""" Header Section """ | |
def create_home_header() -> MainHeader: | |
""" | |
Create the header section for the home page. | |
Returns | |
------- | |
MainHeader | |
An instance of MainHeader with the specified heading and subheading. | |
""" | |
home_heading_input = pn.widgets.TextInput(name="Heading", value=HOME_HEADER_STRING) | |
home_subheading_input = pn.widgets.TextInput( | |
name="Subheading", value="Stingray GUI using HoloViz" | |
) | |
return MainHeader(heading=home_heading_input, subheading=home_subheading_input) | |
""" Main Area Section """ | |
def create_home_main_area() -> MainArea: | |
""" | |
Create the main content area for the home page. | |
This function loads default data files into the global event data list, | |
if they are not already loaded, and defines content for tabs. | |
Returns | |
------- | |
MainArea | |
An instance of MainArea containing tabs with content. | |
""" | |
# Path to the data files | |
data_dir = os.path.join(os.getcwd(), "files", "data") | |
target_file1 = "nomission.evt" | |
file_path1 = os.path.join(data_dir, target_file1) | |
target_file2 = "xte_test.evt.gz" | |
file_path2 = os.path.join(data_dir, target_file2) | |
# Check if the file is already loaded | |
if not any(file_name == "nomission" for file_name, _ in loaded_event_data): | |
try: | |
event_list = EventList.read(file_path1, "ogip") | |
loaded_event_data.append(("nomission", event_list)) | |
print(f"File '{target_file1}' loaded successfully.") | |
except Exception as e: | |
print(f"Failed to load file '{target_file1}': {e}") | |
if not any(file_name == "xte_test" for file_name, _ in loaded_event_data): | |
try: | |
event_list = EventList.read(file_path2, "ogip") | |
loaded_event_data.append(("xte_test.evt.gz", event_list)) | |
print(f"File '{target_file2}' loaded successfully.") | |
except Exception as e: | |
print(f"Failed to load file '{target_file2}': {e}") | |
tab1_content = pn.pane.Markdown(HOME_STINGRAY_TAB_STRING) | |
tab2_content = pn.pane.Markdown(HOME_HOLOVIZ_TAB_STRING) | |
tab3_content = pn.pane.Markdown(HOME_DASHBOARD_TAB_STRING) | |
tabs_content = { | |
"What's Stingray?": tab1_content, | |
"What's HoloViz?": tab2_content, | |
"Dashboard": tab3_content, | |
} | |
return MainArea(tabs_content=tabs_content) | |
""" Output Box Section """ | |
def create_home_output_box() -> OutputBox: | |
""" | |
Create the output box section for the home page. | |
Returns | |
------- | |
OutputBox | |
An instance of OutputBox with predefined content. | |
""" | |
return OutputBox(output_content=HOME_OUTPUT_BOX_STRING) | |
""" Floating Plots """ | |
def create_floating_plot_container(title, content) -> FloatingPlot: | |
""" | |
Create a floating plot container for the home page. | |
Parameters | |
---------- | |
title : str | |
The title of the floating plot. | |
content : pn.viewable.Viewer | |
The content to be displayed in the floating plot. | |
Returns | |
------- | |
FloatingPlot | |
An instance of FloatingPlot with the specified title and content. | |
""" | |
return FloatingPlot(title, content) | |
""" Warning Box Section """ | |
def create_home_warning_box() -> WarningBox: | |
""" | |
Create the warning box section for the home page. | |
Returns | |
------- | |
WarningBox | |
An instance of WarningBox with predefined content. | |
""" | |
return WarningBox(warning_content=HOME_WARNING_BOX_STRING) | |
""" Plots Area Section Initial """ | |
def create_home_plots_area_initial() -> PlotsContainer: | |
""" | |
Create the initial plots area for the home page. | |
This function displays a message instead of generating plots | |
to reduce load time on the first visit. | |
Returns | |
------- | |
PlotsContainer | |
An instance of PlotsContainer with a message. | |
""" | |
text = pn.pane.Markdown( | |
"Not displaying the NICER analysis plots on first load as it takes time to load. Move around the dashboard and come back to home page, to see the analysis plots. The buttons to navigate are in the sidebar." | |
) | |
return PlotsContainer(text) | |
""" Plots Area Section """ | |
def create_home_plots_area() -> PlotsContainer: | |
""" | |
Create the main plots area for the home page. | |
This function generates multiple plots including light curves, | |
histograms of bad time intervals, and comparisons between raw | |
and filled light curves. | |
Returns | |
------- | |
PlotsContainer | |
An instance of PlotsContainer with various plots. | |
""" | |
# Path to the data files | |
data_dir = os.path.join(os.getcwd(), "files", "data") | |
target_file = "data_small.hdf5" | |
file_path = os.path.join(data_dir, target_file) | |
events = EventList.read(file_path, "hdf5", additional_columns=["DET_ID"]) | |
events.fname = file_path | |
# Create the raw light curve and apply GTIs | |
lc_raw = events.to_lc(dt=1) | |
# Matplotlib raw lightcurve plot | |
fig1, ax1 = plt.subplots() | |
lc_raw.plot(ax=ax1) | |
ax1.set_title("Lightcurve of NICER observation of MAXI 1820+070", fontsize=16) | |
raw_lightcurve_pane = pn.pane.Matplotlib(fig1, width=600, height=600) | |
# Same plot but axis limited | |
fig2, ax2 = plt.subplots() | |
lc_raw.plot(ax=ax2, axis_limits=[1.331126e8, 1.331134e8, None, None]) | |
ax2.set_title("Axis limited Lightcurve", fontsize=16) | |
axislimited_lightcurve_pane = pn.pane.Matplotlib(fig2, width=600, height=600) | |
# Statistics on bad time intervals | |
gti_lengths = get_gti_lengths(events.gti) | |
btis = get_btis(events.gti) | |
bti_lengths = get_gti_lengths(btis) | |
fig3, ax3 = plt.subplots() | |
ax3.hist(bti_lengths, bins=np.geomspace(1e-3, 10000, 30)) | |
ax3.set_xlabel("Length of bad time interval") | |
ax3.set_ylabel("Number of intervals") | |
ax3.set_xscale("log") | |
ax3.set_yscale("log") | |
# Add title to the plot | |
ax3.set_title("Histogram of Bad Time Intervals") | |
# Calculate the values | |
total_exposure = get_total_gti_length(events.gti) | |
total_bti_length = get_total_gti_length(btis) | |
total_bti_length_short = get_total_gti_length(btis[bti_lengths < 1]) | |
# Add a text box with the statistics inside the plot | |
stats_text = ( | |
f"Total exposure: {total_exposure:.2f}\n" | |
f"Total BTI length: {total_bti_length:.2f}\n" | |
f"Total BTI length (short BTIs): {total_bti_length_short:.2f}" | |
) | |
anchored_text = AnchoredText(stats_text, loc="upper right", frameon=True) | |
anchored_text.patch.set_boxstyle("round,pad=0.3,rounding_size=0.2") | |
ax3.add_artist(anchored_text) | |
bti_plot_pane = pn.pane.Matplotlib(fig3, width=600, height=600) | |
# Assume the events object is already created and contains the data | |
# Example code for filling bad time intervals | |
# max_length is the longest bad time interval in seconds we want to fill with simulated data. | |
# The buffer size is the region (in seconds) around the bad time interval that we use to | |
# extract the distribution of the data to simulate | |
ev_filled = events.fill_bad_time_intervals(max_length=1, buffer_size=4) | |
# Create a light curve from the filled events | |
lc_filled = ev_filled.to_lc(dt=1) | |
# Create the figure and axis | |
fig4, ax4 = plt.subplots() | |
# Plot the filled light curve | |
lc_filled.plot(ax=ax4, axis_limits=[1.331126e8, 1.331134e8, None, None]) | |
# Add an apt title to the plot | |
ax4.set_title("Light Curve with Simulated Data Filling Short Bad Time Intervals") | |
# Label the axes | |
ax4.set_xlabel("Time (s)") | |
ax4.set_ylabel("Counts") | |
# Embed the plot into a Panel component | |
filled_bti_plot_pane = pn.pane.Matplotlib(fig4, width=600, height=600) | |
# Plot the raw light curve and simulated data on the same plot | |
fig5, ax5 = plt.subplots() | |
# Plot the raw light curve | |
lc_raw.plot(ax=ax5, axis_limits=[1.331126e8, 1.331134e8, None, None]) | |
# Manually add a label to the raw light curve plot | |
ax5.get_lines()[-1].set_label("Raw Light Curve") | |
# Modify the color of the raw light curve plot manually | |
for line in ax5.get_lines(): | |
line.set_color("black") | |
# Plot the filled light curve | |
ax5.plot( | |
lc_filled.time, | |
lc_filled.counts, | |
color="navy", | |
drawstyle="steps-mid", | |
zorder=20, | |
label="Filled Light Curve", | |
) | |
# Add a title and labels | |
ax5.set_title("Comparison of Raw Light Curve and Simulated Data") | |
ax5.set_xlabel("Time (s)") | |
ax5.set_ylabel("Counts") | |
# Add a legend to differentiate between the curves | |
ax5.legend() | |
# Embed the plot into a Panel component | |
comparison_plot_pane = pn.pane.Matplotlib(fig5, width=600, height=600) | |
return PlotsContainer( | |
raw_lightcurve_pane, | |
axislimited_lightcurve_pane, | |
bti_plot_pane, | |
filled_bti_plot_pane, | |
comparison_plot_pane, | |
) | |
""" Help Area Section """ | |
def create_home_help_area() -> HelpBox: | |
""" | |
Create the help section for the home page. | |
Combines the main dashboard help content with additional help | |
for specific sections. | |
Returns | |
------- | |
HelpBox | |
An instance of HelpBox with combined help content. | |
""" | |
help_content = f"{HOME_HELP_BOX_STRING}\n\n{DASHBOARD_HELP_CONTENT}" | |
return HelpBox(help_content=help_content, title="Help Section") | |
""" Footer Section """ | |
def create_home_footer() -> Footer: | |
""" | |
Create the footer section for the home page. | |
Includes additional links such as Privacy Policy, Terms of Service, and Support. | |
Returns | |
------- | |
Footer | |
An instance of Footer with the specified content and links. | |
""" | |
footer_content = "© 2024 Stingray. All rights reserved." | |
additional_links = [ | |
"[Privacy Policy](https://github.com/StingraySoftware/StingrayExplorer/blob/main/PrivacyPolicy.md)", | |
"[Terms of Service](https://github.com/StingraySoftware/StingrayExplorer/blob/main/TermsOfService.md)", | |
"[Contact Us](https://github.com/StingraySoftware/StingrayExplorer/blob/main/ContactUs.md)", | |
"[Support](https://github.com/StingraySoftware/StingrayExplorer/blob/main/Support.md)", | |
"[About Us](https://github.com/StingraySoftware/StingrayExplorer/blob/main/AboutUs.md)", | |
] | |
return Footer( | |
main_content=footer_content, | |
additional_links=additional_links, | |
) | |