import panel as pn import holoviews as hv from utils.app_context import AppContext import pandas as pd import warnings import hvplot.pandas import numpy as np from utils.DashboardClasses import ( MainHeader, MainArea, OutputBox, WarningBox, HelpBox, Footer, WarningHandler, FloatingPlot, PlotsContainer, ) from stingray import Crossspectrum # Create a warning handler def create_warning_handler(): warning_handler = WarningHandler() warnings.showwarning = warning_handler.warn return warning_handler """ Header Section """ def create_quicklook_cross_spectrum_header(context: AppContext): home_heading_input = pn.widgets.TextInput( name="Heading", value="QuickLook Cross Spectrum" ) home_subheading_input = pn.widgets.TextInput(name="Subheading", value="") return MainHeader(heading=home_heading_input, subheading=home_subheading_input) """ Output Box Section """ def create_loadingdata_output_box(content): return OutputBox(output_content=content) """ Warning Box Section """ def create_loadingdata_warning_box(content): return WarningBox(warning_content=content) """ Float Panel """ def create_floatpanel_area(content, title): return FloatingPlot(content=content, title=title) """ Main Area Section """ def create_cross_spectrum_tab( context: AppContext, warning_handler, ): event_list_dropdown_1 = pn.widgets.Select( name="Select Event List 1", options={name: i for i, (name, event) in enumerate(context.state.get_event_data())}, ) event_list_dropdown_2 = pn.widgets.Select( name="Select Event List 2", options={name: i for i, (name, event) in enumerate(context.state.get_event_data())}, ) dt_slider = pn.widgets.FloatSlider( name="Select dt", start=0.1, end=1000, step=0.1, value=1, ) norm_select = pn.widgets.Select( name="Normalization", options=["frac", "leahy", "abs", "none"], value="leahy", ) floatpanel_plots_checkbox = pn.widgets.Checkbox( name="Add Plot to FloatingPanel", value=False ) dataframe_checkbox = pn.widgets.Checkbox( name="Add DataFrame to FloatingPanel", value=False ) def create_holoviews_panes(plot): return pn.pane.HoloViews(plot, width=600, height=600) def create_holoviews_plots(cs, event_list_name_1, event_list_name_2, dt, norm): label = f"{event_list_name_1} vs {event_list_name_2} (dt={dt}, norm={norm})" return hv.Curve((cs.freq, np.abs(cs.power)), label=label).opts( xlabel="Frequency (Hz)", ylabel="Cross Spectral Amplitude", title=label, width=600, height=600, shared_axes=False, ) def create_dataframe_panes(df, title): return pn.FlexBox( pn.pane.Markdown(f"**{title}**"), pn.pane.DataFrame(df, width=600, height=600), align_items="center", justify_content="center", flex_wrap="nowrap", flex_direction="column", ) def create_dataframe(selected_event_list_index_1, selected_event_list_index_2, dt, norm): if selected_event_list_index_1 is not None and selected_event_list_index_2 is not None: event_list_1 = context.state.get_event_data()[selected_event_list_index_1][1] event_list_2 = context.state.get_event_data()[selected_event_list_index_2][1] # Use spectrum service to create cross spectrum result = context.services.spectrum.create_cross_spectrum( event_list_1=event_list_1, event_list_2=event_list_2, dt=dt, norm=norm ) if not result["success"]: context.update_container('output_box', create_loadingdata_output_box(f"Error: {result['message']}") ) return None, None cs = result["data"] # Use export service to convert to DataFrame df_result = context.services.export.to_dataframe_cross_spectrum(cs) if df_result["success"]: return df_result["data"], cs else: context.update_container('output_box', create_loadingdata_output_box(f"Error: {df_result['message']}") ) return None, None return None, None def show_dataframe(event=None): if not context.state.get_event_data(): context.update_container('output_box', create_loadingdata_output_box("No loaded event data available.") ) return selected_event_list_index_1 = event_list_dropdown_1.value selected_event_list_index_2 = event_list_dropdown_2.value if selected_event_list_index_1 is None or selected_event_list_index_2 is None: context.update_container('output_box', create_loadingdata_output_box("Both event lists must be selected.") ) return dt = dt_slider.value norm = norm_select.value df, cs = create_dataframe(selected_event_list_index_1, selected_event_list_index_2, dt, norm) if df is not None: event_list_name_1 = context.state.get_event_data()[selected_event_list_index_1][0] event_list_name_2 = context.state.get_event_data()[selected_event_list_index_2][0] dataframe_title = f"{event_list_name_1} vs {event_list_name_2} (dt={dt}, norm={norm})" dataframe_output = create_dataframe_panes(df, dataframe_title) if dataframe_checkbox.value: context.append_to_container('float_panel', create_floatpanel_area( content=dataframe_output, title=f"DataFrame for {dataframe_title}", ) ) else: context.append_to_container('plots', dataframe_output) else: context.update_container('output_box', create_loadingdata_output_box("Failed to create dataframe.") ) def generate_cross_spectrum(event=None): if not context.state.get_event_data(): context.update_container('output_box', create_loadingdata_output_box("No loaded event data available.") ) return selected_event_list_index_1 = event_list_dropdown_1.value selected_event_list_index_2 = event_list_dropdown_2.value if selected_event_list_index_1 is None or selected_event_list_index_2 is None: context.update_container('output_box', create_loadingdata_output_box("Both event lists must be selected.") ) return dt = dt_slider.value norm = norm_select.value df, cs = create_dataframe(selected_event_list_index_1, selected_event_list_index_2, dt, norm) if df is not None: event_list_name_1 = context.state.get_event_data()[selected_event_list_index_1][0] event_list_name_2 = context.state.get_event_data()[selected_event_list_index_2][0] plot_hv = create_holoviews_plots(cs, event_list_name_1, event_list_name_2, dt, norm) holoviews_output = create_holoviews_panes(plot_hv) if floatpanel_plots_checkbox.value: context.append_to_container('float_panel', create_floatpanel_area( content=holoviews_output, title=f"Cross Spectrum for {event_list_name_1} vs {event_list_name_2} (dt={dt}, norm={norm})" ) ) else: markdown_content = f"## Cross Spectrum for {event_list_name_1} vs {event_list_name_2} (dt={dt}, norm={norm})" context.append_to_container('plots', pn.FlexBox( pn.pane.Markdown(markdown_content), holoviews_output, align_items="center", justify_content="center", flex_wrap="nowrap", flex_direction="column", ) ) else: context.update_container('output_box', create_loadingdata_output_box("Failed to create cross spectrum.") ) generate_cross_spectrum_button = pn.widgets.Button( name="Generate Cross Spectrum", button_type="primary" ) generate_cross_spectrum_button.on_click(generate_cross_spectrum) show_dataframe_button = pn.widgets.Button( name="Show DataFrame", button_type="primary" ) show_dataframe_button.on_click(show_dataframe) tab_content = pn.Column( event_list_dropdown_1, event_list_dropdown_2, dt_slider, norm_select, floatpanel_plots_checkbox, dataframe_checkbox, pn.Row(generate_cross_spectrum_button, show_dataframe_button), ) return tab_content def create_quicklook_cross_spectrum_main_area(context: AppContext): warning_handler = create_warning_handler() tabs_content = { "Cross Spectrum": create_cross_spectrum_tab( context=context, warning_handler=warning_handler, ), } return MainArea(tabs_content=tabs_content) def create_quicklook_cross_spectrum_area(): return PlotsContainer()