Source code for sprit.sprit_jupyter_UI

"""Functions to create jupyter notebook widget UI
"""

import datetime
import inspect
import os
import pathlib
import tkinter as tk
from tkinter import filedialog
import webbrowser

from zoneinfo import available_timezones

import ipywidgets as widgets
from IPython.display import display, clear_output
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import plotly.subplots as subplots
from scipy import signal

try: #For distribution
    from sprit import sprit_utils
    from sprit import sprit_hvsr
except: #For local testing
    import sprit_hvsr 
    import sprit_utils

global hvsr_data
    
OBSPY_FORMATS =  ['AH', 'ALSEP_PSE', 'ALSEP_WTH', 'ALSEP_WTN', 'CSS', 'DMX', 'GCF', 'GSE1', 'GSE2', 'KINEMETRICS_EVT', 'KNET', 'MSEED', 'NNSA_KB_CORE', 'PDAS', 'PICKLE', 'Q', 'REFTEK130', 'RG16', 'SAC', 'SACXY', 'SEG2', 'SEGY', 'SEISAN', 'SH_ASC', 'SLIST', 'SU', 'TSPAIR', 'WAV', 'WIN', 'Y']

[docs] def get_default(func, param): return inspect.signature(func).parameters[param].default
[docs] def create_jupyter_ui(): global hvsr_data ui_width = 20 ui_height= 12 global results_fig global log_textArea log_textArea = widgets.Textarea(value="SESSION LOG", disabled=True, layout={'height': '300px','width': '99%', 'overflow': 'scroll'}) # INPUT TAB # Create a VBox for the accordions input_HBox = widgets.HBox() input_accordion_label_box = widgets.VBox() input_accordion_box = widgets.VBox() input_accordion = widgets.Accordion() # Metadata accordion metadata_grid = widgets.GridspecLayout(7, 10) network_textbox = widgets.Text(description='Network:', placeholder=get_default(sprit_hvsr.input_params, 'network'), value=get_default(sprit_hvsr.input_params, 'network'), tooltip="input_params(network)") station_textbox = widgets.Text(description='Station:', placeholder=get_default(sprit_hvsr.input_params, 'station'), value=get_default(sprit_hvsr.input_params, 'station')) location_textbox = widgets.Text(description='Location:', placeholder=get_default(sprit_hvsr.input_params, 'location'), value=get_default(sprit_hvsr.input_params, 'location')) z_channel_textbox = widgets.Text(description='Z Channel:', placeholder=get_default(sprit_hvsr.input_params, 'channels')[0], value=get_default(sprit_hvsr.input_params, 'channels')[0]) e_channel_textbox = widgets.Text(description='E Channel:', placeholder=get_default(sprit_hvsr.input_params, 'channels')[2], value=get_default(sprit_hvsr.input_params, 'channels')[2]) n_channel_textbox = widgets.Text(description='N Channel:', placeholder=get_default(sprit_hvsr.input_params, 'channels')[1], value=get_default(sprit_hvsr.input_params, 'channels')[1]) # Instrument Settings inst_settings_text = widgets.Text(placeholder='Instrument Settings Filepath', layout=widgets.Layout(width='55%')) instrument_read_button = widgets.Button(icon='fa-file-import',button_style='success', layout=widgets.Layout(width='4%')) instrument_settings_button = widgets.Button(description='Select .inst file', layout=widgets.Layout(width='10%')) inst_settings_hbox = widgets.HBox([inst_settings_text,instrument_read_button, instrument_settings_button]) def select_inst(event): try: if event.description == 'Select .inst file': root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() inst_files = filedialog.askopenfilenames(defaultextension='.inst', filetypes=[('Inst', '.inst')], title="Select Instrument Settings File") if isinstance(inst_files, tuple): pass else: inst_files = tuple(inst_files) root.destroy() else: inst_files = tuple([inst_settings_text.value]) for i, inst_f in enumerate(inst_files): inst_settings_text.value = pathlib.Path(inst_f).as_posix() inst_settings = sprit_hvsr.import_settings(settings_import_path=pathlib.Path(inst_f).as_posix(), settings_import_type='instrument') # Go through all items and add them if 'instrument' in inst_settings.keys(): if inst_settings['instrument'] not in instrument_dropdown.options: instrument_dropdown.options.append(inst_settings['instrument']) instrument_dropdown.value = inst_settings['instrument'] if 'net' in inst_settings.keys(): network_textbox.value = inst_settings['net'] if 'sta' in inst_settings.keys(): station_textbox.value = inst_settings['sta'] if 'location' in inst_settings.keys(): location_textbox.value = inst_settings['location'] if 'cha' in inst_settings.keys(): for c in inst_settings['cha']: if c.lower()[2]=='z': z_channel_textbox.value = c if c.lower()[2]=='e': e_channel_textbox.value = c if c.lower()[2] =='n': n_channel_textbox.value = c if 'metapath' in inst_settings.keys(): metadata_filepath.value = inst_settings['metapath'] if 'hvsr_band' in inst_settings.keys(): hvsr_band_min_box.value = inst_settings['hvsr_band'][0] hvsr_band_max_box.value = inst_settings['hvsr_band'][1] except Exception as e: print(e) instrument_settings_button.disabled=True instrument_settings_button.description='Use Text Field' instrument_settings_button.on_click(select_inst) instrument_read_button.on_click(select_inst) metadata_grid[0,:] = inst_settings_hbox metadata_grid[1,0] = network_textbox metadata_grid[2,0] = station_textbox metadata_grid[3,0] = location_textbox metadata_grid[4,0] = z_channel_textbox metadata_grid[5,0] = e_channel_textbox metadata_grid[6,0] = n_channel_textbox # Acquisition Accordion instrument_grid = widgets.GridspecLayout(5, 10) # Date Picker labelled "Acquisition Date" acquisition_date_picker = widgets.DatePicker(description='Acq.Date:', placeholder=datetime.datetime.today().date(), value=datetime.datetime.today().date()) # Label that shows the Date currently selected in the Date Picker acquisition_doy = widgets.IntText(description='DOY', placeholder=f"{acquisition_date_picker.value.timetuple().tm_yday}", value=f"{acquisition_date_picker.value.timetuple().tm_yday}", layout=widgets.Layout(width='auto')) def on_acq_date_change(change): acquisition_doy.value = acquisition_date_picker.value.timetuple().tm_yday acquisition_date_picker.observe(on_acq_date_change) def on_doy_change(change): curr_year = datetime.datetime.today().year if acquisition_doy.value > datetime.datetime.today().timetuple().tm_yday: curr_year -= 1 acquisition_date_picker.value = (datetime.datetime(curr_year, 1, 1) + datetime.timedelta(days = acquisition_doy.value-1)).date() acquisition_doy.observe(on_doy_change) # Time selector (hour and minute) labelled "Start Time". try: start_time_picker = widgets.TimePicker(description='Start Time:', placeholder=datetime.time(0,0,0), value=datetime.time(0,0,0), layout=widgets.Layout(width='auto')) except Exception as e: start_time_picker = widgets.Text(description='Start Time:', placeholder='00:00', value='00:00', layout=widgets.Layout(width='auto')) # Time selector (hour and minute) labelled "End Time". Same as Start Time otherwise. try: end_time_picker = widgets.TimePicker(description='End Time:', placeholder=datetime.time(23,59), value=datetime.time(23,59), layout=widgets.Layout(width='auto')) except Exception as e: end_time_picker = widgets.Text(description='End Time:', placeholder='23:59:59.999999', value='23:59:59.999999', layout=widgets.Layout(width='auto')) tzlist = list(available_timezones()) tzlist.sort() tzlist.remove('UTC') tzlist.remove('US/Central') tzlist.insert(0, 'US/Central') tzlist.insert(0, 'UTC') # A dropdown list with all the items from zoneinfo.available_timezones(), default 'UTC' time_zone_dropdown = widgets.Dropdown(options=tzlist,value=get_default(sprit_hvsr.input_params, 'tzone'), description='Time Zone:',layout=widgets.Layout(width='fill')) instrument_grid[0,0] = acquisition_date_picker instrument_grid[0,1] = acquisition_doy instrument_grid[1,0] = start_time_picker instrument_grid[2,0] = end_time_picker instrument_grid[3,0] = time_zone_dropdown # LOCATION ACCORDION location_grid = widgets.GridspecLayout(4, 10) # X coordinate input xcoord_textbox = widgets.FloatText(description='X Coordinate:', tooltip='xcoord', value=get_default(sprit_hvsr.input_params, 'xcoord'), placeholder=get_default(sprit_hvsr.input_params, 'xcoord'), layout=widgets.Layout(width='auto')) location_grid[0, 0] = xcoord_textbox # Y coordinate input ycoord_textbox = widgets.FloatText(description='Y Coordinate', tooltip='ycoord:', value=get_default(sprit_hvsr.input_params, 'ycoord'), placeholder=get_default(sprit_hvsr.input_params, 'ycoord'), layout=widgets.Layout(width='auto')) location_grid[1, 0] = ycoord_textbox # Z coordinate input zcoord_textbox = widgets.FloatText(description='Z Coordinate', tooltip='elevation:', value=get_default(sprit_hvsr.input_params, 'elevation'), placeholder=get_default(sprit_hvsr.input_params, 'elevation'), layout=widgets.Layout(width='auto')) location_grid[2, 0] = zcoord_textbox # Z coordinate unit input elevation_unit_textbox = widgets.Dropdown(options=[('Feet', 'feet'), ('Meters', 'meters')], value=get_default(sprit_hvsr.input_params, 'elev_unit'), description='Z Unit:', tooltip='elev_unit', layout=widgets.Layout(width='auto')) location_grid[2, 1] = elevation_unit_textbox # Input CRS input input_crs_textbox = widgets.Text(description='Input CRS:', layout=widgets.Layout(width='auto'), placholder=get_default(sprit_hvsr.input_params, 'input_crs'), value=get_default(sprit_hvsr.input_params, 'input_crs')) location_grid[3, 0] = input_crs_textbox # Output CRS input output_crs_textbox = widgets.Text(description='Output CRS:', layout=widgets.Layout(width='auto'), placholder=get_default(sprit_hvsr.input_params, 'output_crs'), value=get_default(sprit_hvsr.input_params, 'output_crs')) location_grid[3, 1] = output_crs_textbox # IO PARAMS ACCORDION ioparam_grid = widgets.GridspecLayout(6, 10) # Data format (for obspy format to use to read in) data_format_dropdown = widgets.Dropdown( options=OBSPY_FORMATS, value='MSEED', description='Data Formats:', layout=widgets.Layout(width='auto')) hvsr_band_min_box = widgets.FloatText(description='HVSR Band [Hz]', style={'description_width': 'initial'}, placeholder=get_default(sprit_hvsr.input_params, 'hvsr_band')[0], value=get_default(sprit_hvsr.input_params, 'hvsr_band')[0]) hvsr_band_max_box = widgets.FloatText(placeholder=get_default(sprit_hvsr.input_params, 'hvsr_band')[1], value=get_default(sprit_hvsr.input_params, 'hvsr_band')[1]) hvsr_band_hbox = widgets.HBox([hvsr_band_min_box, hvsr_band_max_box],layout=widgets.Layout(width='auto')) peak_freq_range_min_box = widgets.FloatText(description='Peak Range [Hz]',placeholder=get_default(sprit_hvsr.input_params, 'peak_freq_range')[0], value=get_default(sprit_hvsr.input_params, 'peak_freq_range')[0], style={'description_width': 'initial'}, layout=widgets.Layout(width='auto')) peak_freq_range_max_box = widgets.FloatText(placeholder=get_default(sprit_hvsr.input_params, 'peak_freq_range')[1], value=get_default(sprit_hvsr.input_params, 'peak_freq_range')[1],layout=widgets.Layout(width='auto')) peak_freq_range_hbox = widgets.HBox([peak_freq_range_min_box, peak_freq_range_max_box],layout=widgets.Layout(width='auto')) # A dropdown labeled "Detrend type" with "Spline", "Polynomial", or "None" detrend_type_dropdown = widgets.Dropdown(options=[('Spline', 'spline'), ('Polynomial', 'polynomial'), ('None', 'none')], description='Detrend Type:', layout=widgets.Layout(width='auto')) detrend_options = widgets.FloatText(description='Order:', tooltip='detrend_options', placeholder=get_default(sprit_hvsr.fetch_data, 'detrend_options'), value=get_default(sprit_hvsr.fetch_data, 'detrend_options'),layout=widgets.Layout(width='auto')) # A text to specify the trim directory trim_directory = widgets.Text(description='Trim Dir.:', value="None",#pathlib.Path().home().as_posix(), layout=widgets.Layout(width='auto')) trim_export_dropdown = widgets.Dropdown( options=OBSPY_FORMATS, value='MSEED', description='Trim Format:', layout=widgets.Layout(width='auto')) trim_directory_upload = widgets.FileUpload( accept='', multiple=False, layout=widgets.Layout(width='auto')) # Processing Settings proc_settings_text = widgets.Text(placeholder='Instrument Settings Filepath', layout=widgets.Layout(width='55%')) proc_settings_read_button = widgets.Button(icon='fa-file-import',button_style='success', layout=widgets.Layout(width='4%')) proc_settings_browse_button = widgets.Button(description='Select .proc file', layout=widgets.Layout(width='10%')) proc_settings_hbox = widgets.HBox([proc_settings_text, proc_settings_read_button, proc_settings_browse_button]) excluded_params = ['hvsr_data', 'params', 'hvsr_results'] funcList = [sprit_hvsr.fetch_data, sprit_hvsr.remove_noise, sprit_hvsr.generate_psds, sprit_hvsr.process_hvsr, sprit_hvsr.remove_outlier_curves, sprit_hvsr.check_peaks, sprit_hvsr.get_report] def select_proc(event): try: if event.description == 'Select .proc file': root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() proc_files = filedialog.askopenfilenames(defaultextension='.proc', filetypes=[('PROC', '.proc')], title="Select Processing Settings File") if isinstance(proc_files, tuple): pass else: proc_files = tuple(proc_files) root.destroy() else: proc_files = tuple([proc_settings_text.value]) for i, proc_f in enumerate(proc_files): proc_settings_text.value = pathlib.Path(proc_f).as_posix() proc_settings = sprit_hvsr.import_settings(settings_import_path=pathlib.Path(proc_f).as_posix(), settings_import_type='processing') for func, params in proc_settings.items(): if func in widget_param_dict.keys(): for prm, val in params.items(): if prm in widget_param_dict[func].keys(): #print(prm, ':', widget_param_dict[func][prm],' | ', val) if val is None or val=='None': val='none' if prm == 'export_format': val = val.upper() if prm == 'smooth': if val is True: val = 51 if prm == 'resample': if val is True: val = 1000 if isinstance(widget_param_dict[func][prm], list): for i, item in enumerate(widget_param_dict[func][prm]): item.value = val[i] else: widget_param_dict[func][prm].value = val except Exception as e: print(e) proc_settings_browse_button.disabled=True proc_settings_browse_button.description='Use Text Field' proc_settings_read_button.on_click(select_proc) proc_settings_browse_button.on_click(select_proc) ioparam_grid[0,:] = proc_settings_hbox ioparam_grid[1,0] = data_format_dropdown ioparam_grid[2,:5] = hvsr_band_hbox ioparam_grid[3,:5] = peak_freq_range_hbox ioparam_grid[4,:1] = detrend_type_dropdown ioparam_grid[4,1] = detrend_options ioparam_grid[5,:6] = trim_directory ioparam_grid[5, 6:8] = trim_export_dropdown ioparam_grid[5, 8] = trim_directory_upload # PYTHON API ACCORDION inputAPI_grid = widgets.GridspecLayout(2, 10) # A text label with "input_params()" input_params_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'input_params' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) input_params_call = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + '()' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-start',align_content='flex-start'),) #input_params_call = widgets.Label(value='input_params()', layout=widgets.Layout(width='auto')) inputAPI_grid[0, 0] = input_params_prefix inputAPI_grid[0, 1:] = input_params_call # A text label with "fetch_data()" fetch_data_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'fetch_data' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) fetch_data_call = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + '()' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-start',align_content='flex-start'),) inputAPI_grid[1, 0] = fetch_data_prefix inputAPI_grid[1, 1:] = fetch_data_call # Set it all in place metaLabel = widgets.Label('Instrument', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) instLabel = widgets.Label('Acquisition', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) locLabel = widgets.Label('Location', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) ioparmLabel = widgets.Label('IO/Params', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) apiLabel = widgets.Label('API Call', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) input_accordion_label_box.children = [metaLabel, instLabel, locLabel, ioparmLabel, apiLabel] input_accordion_label_box.layout = widgets.Layout(align_content='space-between', width='5%') input_accordion.children = [metadata_grid, instrument_grid, location_grid, ioparam_grid, inputAPI_grid] input_accordion.titles = ["Instrument Metadata", "Acquisition Information", "Location Information", "I/O and Parameters", "See Python API Call"] input_accordion_box.layout = widgets.Layout(align_content='space-between', width='99%') input_accordion.layout = widgets.Layout(width='99%') # ADD THE REST OF THE WIDGETS AROUND THE ACCORDIONS # A text box for the site name site_name = widgets.Text(description='Site Name:', value='HVSR_Site', placeholder='HVSR_Site', style={'description_width': 'initial'}, layout=widgets.Layout(width='30%')) tenpct_spacer = widgets.Button(description='', layout=widgets.Layout(width='20%', visibility='hidden')) # Dropdown with different source types data_source_type = widgets.Dropdown(options=[('File', 'file'), ('Raw', 'raw'), ('Batch', 'batch'), ('Directory', 'dir')], description='Data Source type:', value='file',orientation='horizontal', style={'description_width': 'initial'}, layout=widgets.Layout(width='20%')) def on_ds_change(event): if data_source_type.value == 'file' or data_source_type.value== 'batch': browse_data_button.description = 'Select Files' else: browse_data_button.description = 'Select Folders' data_source_type.observe(on_ds_change) # Dropdown labeled "Instrument" with options "Raspberry Shake", "Tromino", "Other" instrument_dropdown = widgets.Dropdown(options=['Raspberry Shake', 'Tromino', 'Other'], style={'description_width': 'initial'}, description='Instrument:',layout=widgets.Layout(width='20%')) # Processing Settings processing_settings_button = widgets.FileUpload(accept='.proc', description='Processing Settings', multiple=False,layout=widgets.Layout(width='10%')) # Whether to show plots outside of widget show_plot_check = widgets.Checkbox(description='Print Plots', value=False, disabled=False, indent=False, layout=widgets.Layout(width='10%', justify_content='flex-end')) # Whether to print to terminal verbose_check = widgets.Checkbox(description='Verbose', value=False, disabled=False, indent=False, layout=widgets.Layout(width='10%', justify_content='flex-end')) # A text box labeled Data Filepath data_filepath = widgets.Text(description='Data Filepath:', placeholder='sample', value='sample', style={'description_width': 'initial'},layout=widgets.Layout(width='70%')) # A button next to it labeled "Browse" browse_data_button = widgets.Button(description='Select Files', layout=widgets.Layout(width='10%')) def select_datapath(event): try: root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() if data_source_type.value=='file' or data_source_type.value=='batch': data_filepath.value = str(filedialog.askopenfilenames(defaultextension='.MSEED', title='Select Data File')) else: data_filepath.value = str(filedialog.askdirectory(mustexist=True, title="Select Data Directory")) root.destroy() except Exception as e: print(e) browse_data_button.disabled=True browse_data_button.description='Use Text Field' browse_data_button.on_click(select_datapath) # A text box labeled Metadata Filepath metadata_filepath = widgets.Text(description='Metadata Filepath:', style={'description_width': 'initial'},layout=widgets.Layout(width='70%')) # A button next to it labeled "Browse" browse_metadata_button = widgets.Button(description='Select File(s)', layout=widgets.Layout(width='10%')) def select_metapath(event): try: root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() metadata_filepath.value = str(filedialog.askopenfilenames(title='Select Metadata File(s)')) root.destroy() except Exception as e: print(e) browse_metadata_button.disabled=True browse_metadata_button.description='Use Text Field' browse_metadata_button.on_click(select_metapath) # A progress bar progress_bar = widgets.FloatProgress(value=0.0,min=0.0,max=1.0, bar_style='info', orientation='horizontal',layout=widgets.Layout(width='85%')) # A dark yellow button labeled "Read Data" read_data_button = widgets.Button(description='Read Data', button_style='warning',layout=widgets.Layout(width='10%')) # A forest green button labeled "Process HVSR" process_hvsr_button = widgets.Button(description='Run', button_style='success',layout=widgets.Layout(width='5%')) # Update input_param call def update_input_param_call(): input_param_text = f"""(input_data='{data_filepath.value}', metapath='{metadata_filepath.value}', site='{site_name.value}', network='{network_textbox.value}', station='{station_textbox.value}', location='{location_textbox.value}', loc='{location_textbox.value}', channels={[z_channel_textbox.value, e_channel_textbox.value, n_channel_textbox.value]}, acq_date='{acquisition_date_picker.value}', starttime='{start_time_picker.value}', endtime='{end_time_picker.value}', tzone='{time_zone_dropdown.value}', xcoord={xcoord_textbox.value}, ycoord={ycoord_textbox.value}, elevation={zcoord_textbox.value}, depth=0 input_crs='{input_crs_textbox.value}', output_crs='{output_crs_textbox.value}', elev_unit='{elevation_unit_textbox.value}', instrument='{instrument_dropdown.value}', hvsr_band={[hvsr_band_min_box.value, hvsr_band_max_box.value]}, peak_freq_range={[peak_freq_range_min_box.value, peak_freq_range_max_box.value]}, verbose={verbose_check.value})""" input_params_call.value='<style>p {word-wrap: break-word}</style> <p>' + input_param_text + '</p>' update_input_param_call() # Update fetch_data call def update_fetch_data_call(): fetch_data_text = f"""(params=hvsr_data, source={data_source_type.value}, trim_dir={trim_directory.value}, export_format={trim_export_dropdown.value}, detrend={detrend_type_dropdown.value}, detrend_options={detrend_options.value}, verbose={verbose_check.value})""" fetch_data_call.value='<style>p {word-wrap: break-word}</style> <p>' + fetch_data_text + '</p>' update_fetch_data_call() site_hbox = widgets.HBox() site_hbox.children = [site_name, tenpct_spacer, tenpct_spacer, tenpct_spacer, tenpct_spacer, tenpct_spacer, show_plot_check, verbose_check] datapath_hbox = widgets.HBox() datapath_hbox.children = [data_filepath, browse_data_button, data_source_type] metadata_hbox = widgets.HBox() metadata_hbox.children = [metadata_filepath, browse_metadata_button, instrument_dropdown] progress_hbox = widgets.HBox() progress_hbox.children = [progress_bar, read_data_button, process_hvsr_button] input_params_vbox = widgets.VBox() input_params_vbox.children = [site_hbox,datapath_hbox,metadata_hbox,progress_hbox] input_accordion_box.children = [input_accordion] #input_HBox.children = [input_accordion_label_box, input_accordion_box] #input_HBox.layout= widgets.Layout(align_content='space-between') # Create a GridBox with 12 rows and 20 columns input_tab = widgets.GridBox(layout=widgets.Layout(grid_template_columns='repeat(10, 1)', grid_template_rows='repeat(12, 1)')) # Add the VBox to the GridBox input_tab.children = [site_hbox, datapath_hbox, metadata_hbox, input_accordion_box, progress_hbox] def get_input_params(): input_params_kwargs={ 'input_data':data_filepath.value, 'metapath':metadata_filepath.value, 'site':site_name.value, 'instrument':instrument_dropdown.value, 'network':network_textbox.value, 'station':station_textbox.value, 'location':location_textbox.value, 'channels':[z_channel_textbox.value, e_channel_textbox.value, n_channel_textbox.value], 'starttime':start_time_picker.value, 'endtime':end_time_picker.value, 'tzone':time_zone_dropdown.value, 'xcoord':xcoord_textbox.value, 'ycoord':ycoord_textbox.value, 'elevation':zcoord_textbox.value, 'elev_unit':elevation_unit_textbox.value,'depth':0, 'input_crs':input_crs_textbox.value,'output_crs':output_crs_textbox.value, 'hvsr_band':[hvsr_band_min_box.value, hvsr_band_max_box.value], 'peak_freq_range':[peak_freq_range_min_box.value, peak_freq_range_max_box.value]} return input_params_kwargs def get_fetch_data_params(): fetch_data_kwargs = { 'source':data_source_type.value, 'trim_dir':trim_directory.value, 'export_format':data_format_dropdown.value, 'detrend':detrend_type_dropdown.value, 'detrend_options':detrend_options.value} if str(fetch_data_kwargs['detrend']).lower() == 'none': fetch_data_kwargs['detrend'] = None if str(fetch_data_kwargs['trim_dir']).lower() == 'none': fetch_data_kwargs['trim_dir'] = None return fetch_data_kwargs def read_data(button): progress_bar.value = 0 log_textArea.value += f"\n\nREADING DATA [{datetime.datetime.now()}]" ip_kwargs = get_input_params() hvsr_data = sprit_hvsr.input_params(**ip_kwargs, verbose=verbose_check.value) log_textArea.value += f"\n\n{datetime.datetime.now()}\ninput_params():\n'{ip_kwargs}" if button.description=='Read Data': progress_bar.value=0.333 else: progress_bar.value=0.1 fd_kwargs = get_fetch_data_params() hvsr_data = sprit_hvsr.fetch_data(hvsr_data, **fd_kwargs, verbose=verbose_check.value) log_textArea.value += '\n\n'+str(datetime.datetime.now())+'\nfetch_data():\n\t'+str(fd_kwargs) if button.description=='Read Data': progress_bar.value=0.666 else: progress_bar.value=0.2 use_hv_curve_rmse.value=False use_hv_curve_rmse.disabled=True update_preview_fig(hvsr_data, preview_fig) if button.description=='Read Data': sprit_tabs.selected_index = 1 progress_bar.value=0 return hvsr_data read_data_button.on_click(read_data) def get_remove_noise_kwargs(): def get_remove_method(): remove_method_list=[] do_stalta = stalta_check.value do_sat_pct = max_saturation_check.value do_noiseWin=noisy_windows_check.value do_warmcool=warmcool_check.value if auto_remove_check.value: remove_method_list=['stalta', 'saturation', 'noise', 'warmcool'] else: if do_stalta: remove_method_list.append('stalta') if do_sat_pct: remove_method_list.append('saturation') if do_noiseWin: remove_method_list.append('noise') if do_warmcool: remove_method_list.append('warmcool') if not remove_method_list: remove_method_list = None return remove_method_list remove_noise_kwargs = {'remove_method':get_remove_method(), 'sat_percent':max_saturation_pct.value, 'noise_percent':max_window_pct.value, 'sta':sta.value, 'lta':lta.value, 'stalta_thresh':[stalta_thresh_low.value, stalta_thresh_hi.value], 'warmup_time':warmup_time.value, 'cooldown_time':cooldown_time.value, 'min_win_size':noisy_window_length.value, 'remove_raw_noise':raw_data_remove_check.value, 'verbose':verbose_check.value} return remove_noise_kwargs def get_generate_ppsd_kwargs(): ppsd_kwargs = { 'skip_on_gaps':skip_on_gaps.value, 'db_bins':[db_bins_min.value, db_bins_max.value, db_bins_step.value], 'ppsd_length':ppsd_length.value, 'overlap':overlap_pct.value, 'special_handling':special_handling_dropdown.value, 'period_smoothing_width_octaves':period_smoothing_width.value, 'period_step_octaves':period_step_octave.value, 'period_limits':[period_limits_min.value, period_limits_max.value], 'verbose':verbose_check.value } if str(ppsd_kwargs['special_handling']).lower() == 'none': ppsd_kwargs['special_handling'] = None return ppsd_kwargs def get_remove_outlier_curve_kwargs(): roc_kwargs = { 'use_percentile':rmse_pctile_check.value, 'rmse_thresh':rmse_thresh.value, 'use_hv_curve':False, 'verbose':verbose_check.value } return roc_kwargs def get_process_hvsr_kwargs(): if smooth_hv_curve_bool.value: smooth_value = smooth_hv_curve.value else: smooth_value = smooth_hv_curve_bool.value if resample_hv_curve_bool.value: resample_value = resample_hv_curve.value else: resample_value = resample_hv_curve_bool.value ph_kwargs={'method':h_combine_meth.value, 'smooth':smooth_value, 'freq_smooth':freq_smoothing.value, 'f_smooth_width':freq_smooth_width.value, 'resample':resample_value, 'outlier_curve_rmse_percentile':use_hv_curve_rmse.value, 'verbose':verbose_check.value} return ph_kwargs def get_check_peaks_kwargs(): cp_kwargs = {'hvsr_band':[hvsr_band_min_box.value, hvsr_band_max_box.value], 'peak_freq_range':[peak_freq_range_min_box.value, peak_freq_range_max_box.value], 'peak_selection':peak_selection_type.value, 'verbose':verbose_check.value} return cp_kwargs def get_get_report_kwargs(): def get_formatted_plot_str(): # Initialize plot string hvsr_plot_str = '' comp_plot_str = '' spec_plot_str = '' # Whether to use each plot if use_plot_hv.value: hvsr_plot_str=hvsr_plot_str + "HVSR" if use_plot_comp.value: comp_plot_str=comp_plot_str + "C" if use_plot_spec.value: spec_plot_str=spec_plot_str + "SPEC" # Whether components be on the same plot as HV curve? if not combine_hv_comp.value: comp_plot_str=comp_plot_str + "+" else: comp_plot_str=comp_plot_str.replace('+','') # Whether to show (log) standard deviations if not show_std_hv.value: hvsr_plot_str=hvsr_plot_str + " -s" if not show_std_comp.value: comp_plot_str=comp_plot_str + " -s" # Whether to show all peaks if show_all_peaks_hv.value: hvsr_plot_str=hvsr_plot_str + " all" # Whether curves from each time window are shown if show_all_curves_hv.value: hvsr_plot_str=hvsr_plot_str + " t" if show_all_curves_comp.value: comp_plot_str=comp_plot_str + " t" # Whether the best peak is displayed if show_best_peak_hv.value: hvsr_plot_str=hvsr_plot_str + " p" if show_best_peak_comp.value: comp_plot_str=comp_plot_str + " p" if show_best_peak_spec.value: spec_plot_str=spec_plot_str + " p" # Whether best peak value is annotated if ann_best_peak_hv.value: hvsr_plot_str=hvsr_plot_str + " ann" if ann_best_peak_comp.value: comp_plot_str=comp_plot_str + " ann" if ann_best_peak_spec.value: spec_plot_str=spec_plot_str + " ann" # Whether peaks from individual time windows are shown if show_ind_peaks_hv.value: hvsr_plot_str=hvsr_plot_str + " tp" if show_ind_peaks_spec.value: spec_plot_str=spec_plot_str + ' tp' # Whether to show legend if show_legend_hv.value: hvsr_plot_str=hvsr_plot_str + " leg" if ann_best_peak_comp.value: comp_plot_str=comp_plot_str + " leg" if show_legend_spec.value: spec_plot_str=spec_plot_str + " leg" # Combine string into one plot_str = hvsr_plot_str + ' ' + comp_plot_str+ ' ' + spec_plot_str return plot_str gr_kwargs = {'report_format':['print','csv'], 'plot_type':get_formatted_plot_str(), 'export_path':None, 'csv_overwrite_opt':'overwrite', 'no_output':False, 'verbose':verbose_check.value } return gr_kwargs def process_data(button): startProc=datetime.datetime.now() progress_bar.value = 0 log_textArea.value += f"\n\nPROCESSING DATA [{startProc}]" global hvsr_data # Read data again only if internal hvsr_data input_data variable is different from what is in the gui if not 'hvsr_data' in globals() or not hasattr(hvsr_data, 'input_data') or \ (pathlib.Path(hvsr_data.input_data).as_posix() != pathlib.Path(data_filepath.value).as_posix()): hvsr_data = read_data(button) remove_noise_kwargs = get_remove_noise_kwargs() hvsr_data = sprit_hvsr.remove_noise(hvsr_data, **remove_noise_kwargs) log_textArea.value += f"\n\n{datetime.datetime.now()}\nremove_noise()\n\t{remove_noise_kwargs}" progress_bar.value = 0.3 generate_ppsd_kwargs = get_generate_ppsd_kwargs() hvsr_data = sprit_hvsr.generate_psds(hvsr_data, **generate_ppsd_kwargs) progress_bar.value = 0.5 log_textArea.value += f"\n\n{datetime.datetime.now()}\ngenerate_ppsds()\n\t{generate_ppsd_kwargs}" # If this was started by clicking "Generate PPSDs", stop here if button.description == 'Generate PPSDs': return ph_kwargs = get_process_hvsr_kwargs() hvsr_data = sprit_hvsr.process_hvsr(hvsr_data, **ph_kwargs) log_textArea.value += f"\n\n{datetime.datetime.now()}\nprocess_hvsr()\n\t{ph_kwargs}" progress_bar.value = 0.75 update_outlier_fig() roc_kwargs = get_remove_outlier_curve_kwargs() hvsr_data = sprit_hvsr.remove_outlier_curves(hvsr_data, **roc_kwargs) log_textArea.value += f"\n\n{datetime.datetime.now()}\nremove_outlier_curves()\n\t{roc_kwargs}" progress_bar.value = 0.85 outlier_fig, hvsr_data = update_outlier_fig() use_hv_curve_rmse.value=False use_hv_curve_rmse.disabled=False def get_rmse_range(): minRMSE = 10000 maxRMSE = -1 if roc_kwargs['use_hv_curve']: colnames = ['HV_Curves'] else: colnames = ['psd_values_Z', 'psd_values_E', 'psd_values_N'] dataList = [] for col in colnames: dataArr = np.stack(hvsr_data.hvsr_windows_df[col]) medCurveArr = np.nanmedian(dataArr, axis=0) rmse = np.sqrt(((np.subtract(dataArr, medCurveArr)**2).sum(axis=1))/dataArr.shape[1]) if rmse.min() < minRMSE: minRMSE = rmse.min() if rmse.max() > maxRMSE: maxRMSE = rmse.max() rmse_thresh_slider.min = minRMSE rmse_thresh_slider.max = maxRMSE rmse_thresh_slider.step = round((maxRMSE-minRMSE)/100, 2) rmse_thresh_slider.value = maxRMSE get_rmse_range() cp_kwargs = get_check_peaks_kwargs() hvsr_data = sprit_hvsr.check_peaks(hvsr_data, **cp_kwargs) log_textArea.value += f"\n\n{datetime.datetime.now()}\ncheck_peaks()\n\t{cp_kwargs}" progress_bar.value = 0.9 gr_kwargs = get_get_report_kwargs() hvsr_data = sprit_hvsr.get_report(hvsr_data, **gr_kwargs) log_textArea.value += f"\n\n{datetime.datetime.now()}\nget_report()\n\t{gr_kwargs}\n\n" hvsr_data.get_report(report_format='print') # Just in case print wasn't included log_textArea.value += hvsr_data['Print_Report'] printed_results_textArea.value = hvsr_data['Print_Report'] hvsr_data.get_report(report_format='csv') results_table.value = hvsr_data['CSV_Report'].to_html() log_textArea.value += f'Processing time: {datetime.datetime.now() - startProc}' progress_bar.value = 0.95 update_results_fig(hvsr_data, gr_kwargs['plot_type']) progress_bar.value = 1 global hvsr_results hvsr_results = hvsr_data return hvsr_results def parse_plot_string(plot_string): plot_list = plot_string.split() hvsrList = ['hvsr', 'hv', 'h'] compList = ['component', 'comp', 'c'] compPlus = [item + '+' for item in compList] specList = ['spectrogram', 'specgram', 'spec','sg', 's'] hvInd = np.nan compInd = np.nan specInd = np.nan hvIndFound = False compIndFound = False specIndFound = False for i, item in enumerate(plot_list): if item.lower() in hvsrList and not hvIndFound: # assign the index hvInd = i hvIndFound = True if (item.lower() in compList or item.lower() in compPlus) and not compIndFound: # assign the index compInd = i compIndFound = True if item.lower() in specList and not specIndFound: # assign the index specInd = i specIndFound = True # Get individual plot lists (should already be correctly ordered) if hvInd is np.nan: hvsr_plot_list = ['HVSR'] if compInd is np.nan: comp_plot_list = [] if specInd is np.nan: if hvInd is not np.nan: hvsr_plot_list = plot_list spec_plot_list = [] else: if hvInd is not np.nan: hvsr_plot_list = plot_list[hvInd:specInd] spec_plot_list = plot_list[specInd:] else: if hvInd is not np.nan: hvsr_plot_list = plot_list[hvInd:compInd] if specInd is np.nan: comp_plot_list = plot_list[compInd:] spec_plot_list = [] else: comp_plot_list = plot_list[compInd:specInd] spec_plot_list = plot_list[specInd:] # Figure out how many subplots there will be plot_list_list = [hvsr_plot_list, comp_plot_list, spec_plot_list] return plot_list_list def parse_hv_plot_list(hv_data, hvsr_plot_list, azimuth='HV'): hvsr_data = hv_data x_data = hvsr_data.x_freqs['Z'] hvsrDF = hvsr_data.hvsr_windows_df if azimuth == 'HV': HVCol = 'HV_Curves' else: HVCol = 'HV_Curves_'+azimuth if 'tp' in hvsr_plot_list: allpeaks = [] for row in hvsrDF[hvsrDF['Use']]['CurvesPeakFreqs_'+azimuth].values: for peak in row: allpeaks.append(peak) allInd = [] for row, peakList in enumerate(hvsrDF[hvsrDF['Use']]['CurvesPeakIndices_'+azimuth].values): for ind in peakList: allInd.append((row, ind)) x_vals = [] y_vals = [] y_max = np.nanmax(hvsr_data.hvsrp[azimuth]) hvCurveInd = list(hvsrDF.columns).index(HVCol) for i, tp in enumerate(allpeaks): x_vals.extend([tp, tp, None]) # add two x values and a None y_vals.extend([0, hvsrDF.iloc[allInd[i][0], hvCurveInd][allInd[i][1]], None]) # add the first and last y values and a None results_fig.add_trace(go.Scatter(x=x_vals, y=y_vals, mode='lines', line=dict(width=4, dash="solid", color="rgba(128,0,0,0.1)"), name='Best Peaks Over Time'), row=1, col=1) if 't' in hvsr_plot_list: alltimecurves = np.stack(hvsrDF[hvsrDF['Use']][HVCol]) for i, row in enumerate(alltimecurves): if i==0: showLeg = True else: showLeg= False results_fig.add_trace(go.Scatter(x=x_data[:-1], y=row, mode='lines', line=dict(width=0.5, dash="solid", color="rgba(100, 110, 100, 0.8)"), showlegend=showLeg, name='Ind. time win. curve', hoverinfo='none'), row=1, col=1) if 'all' in hvsr_plot_list: for i, p in enumerate(hvsr_data['hvsr_peak_freqs'][azimuth]): if i==0: showLeg = True else: showLeg= False results_fig.add_trace(go.Scatter( x=[p, p, None], # set x to None y=[0, np.nanmax(np.stack(hvsrDF[HVCol])),None], # set y to None mode="lines", # set mode to lines line=dict(width=1, dash="dot", color="gray"), # set line properties name="All checked peaks", # set legend name showlegend=showLeg), row=1, col=1) if '-s' not in hvsr_plot_list: # Show standard deviation results_fig.add_trace(go.Scatter(x=x_data, y=hvsr_data.hvsrp2[azimuth], line={'color':'black', 'width':0.1},marker=None, showlegend=False, name='Log. St.Dev. Upper', hoverinfo='none'), row=1, col=1) results_fig.add_trace(go.Scatter(x=x_data, y=hvsr_data.hvsrm2[azimuth], line={'color':'black', 'width':0.1},marker=None, fill='tonexty', fillcolor="rgba(128, 128, 128, 0.6)", name='Log. St.Dev.', hoverinfo='none'), row=1, col=1) if 'p' in hvsr_plot_list: results_fig.add_trace(go.Scatter( x=[hvsr_data['BestPeak'][azimuth]['f0'], hvsr_data['BestPeak'][azimuth]['f0'], None], # set x to None y=[0,np.nanmax(np.stack(hvsrDF['HV_Curves'])),None], # set y to None mode="lines", # set mode to lines line=dict(width=1, dash="dash", color="black"), # set line properties name="Best Peak"), row=1, col=1) if 'ann' in hvsr_plot_list: # Annotate best peak results_fig.add_annotation(x=np.log10(hvsr_data['BestPeak'][azimuth]['f0']), y=0, yanchor='bottom', xanchor='center', text=f"{hvsr_data['BestPeak'][azimuth]['f0']:.3f} Hz", bgcolor='rgba(255, 255, 255, 0.7)', showarrow=False, row=1, col=1) return results_fig def parse_comp_plot_list(hv_data, comp_plot_list, azimuth='HV'): hvsr_data = hv_data # Initial setup x_data = hvsr_data.x_freqs['Z'] hvsrDF = hvsr_data.hvsr_windows_df same_plot = ((comp_plot_list != []) and ('+' not in comp_plot_list[0])) if same_plot: yaxis_to_use = 'y2' use_secondary = True transparency_modifier = 0.5 else: yaxis_to_use = 'y' use_secondary=False transparency_modifier = 1 alpha = 0.4 * transparency_modifier components = ['Z', 'E', 'N'] compColor_semi_light = {'Z':f'rgba(128,128,128,{alpha})', 'E':f'rgba(0,0,128,{alpha})', 'N':f'rgba(128,0,0,{alpha})'} alpha = 0.7 * transparency_modifier compColor_semi = {'Z':f'rgba(128,128,128,{alpha})', 'E':f'rgba(100,100,128,{alpha})', 'N':f'rgba(128,100,100,{alpha})'} compColor = {'Z':f'rgba(128,128,128,{alpha})', 'E':f'rgba(100,100,250,{alpha})', 'N':f'rgba(250,100,100,{alpha})'} for az in hvsr_data.hvsr_az.keys(): components.append(az) compColor_semi_light[az] = f'rgba(0,128,0,{alpha})' compColor_semi[az] = f'rgba(100,128,100,{alpha})' compColor[az] = f'rgba(100,250,100,{alpha})' # Whether to plot in new subplot or not if comp_plot_list != [] and '+' in comp_plot_list[0]: compRow=2 else: compRow=1 # Whether to plot individual time curves if 't' in comp_plot_list: for comp in components: alltimecurves = np.stack(hvsrDF[hvsrDF['Use']]['psd_values_'+comp]) for i, row in enumerate(alltimecurves): if i==0: showLeg = True else: showLeg= False results_fig.add_trace(go.Scatter(x=x_data[:-1], y=row, mode='lines', line=dict(width=0.5, dash="solid", color=compColor_semi[comp]), name='Ind. time win. curve', showlegend=False, hoverinfo='none', yaxis=yaxis_to_use), secondary_y=use_secondary, row=compRow, col=1) # Code to plot standard deviation windows, if not removed if '-s' not in comp_plot_list: for comp in components: # Show standard deviation results_fig.add_trace(go.Scatter(x=x_data, y=hvsr_data.ppsd_std_vals_p[comp], line={'color':compColor_semi_light[comp], 'width':0.1},marker=None, showlegend=False, name='Log. St.Dev. Upper', hoverinfo='none', yaxis=yaxis_to_use), secondary_y=use_secondary, row=compRow, col=1) results_fig.add_trace(go.Scatter(x=x_data, y=hvsr_data.ppsd_std_vals_m[comp], line={'color':compColor_semi_light[comp], 'width':0.1},marker=None, fill='tonexty', fillcolor=compColor_semi_light[comp], name=f'St.Dev. [{comp}]', hoverinfo='none', showlegend=False, yaxis=yaxis_to_use), secondary_y=use_secondary, row=compRow, col=1) # Code to plot location of best peak if 'p' in comp_plot_list: minVal = 10000 maxVal = -10000 for comp in components: currPPSDCurve = hvsr_data['psd_values_tavg'][comp] if np.nanmin(currPPSDCurve) < minVal: minVal = np.nanmin(currPPSDCurve) if np.nanmax(currPPSDCurve) > maxVal: maxVal = np.nanmax(currPPSDCurve) results_fig.add_trace(go.Scatter( x=[hvsr_data['BestPeak'][azimuth]['f0'], hvsr_data['BestPeak'][azimuth]['f0'], None], # set x to None y=[minVal,maxVal,None], # set y to None mode="lines", # set mode to lines line=dict(width=1, dash="dash", color="black"), # set line properties name="Best Peak", yaxis=yaxis_to_use), secondary_y=use_secondary, row=compRow, col=1) # Code to annotate value of best peak if 'ann' in comp_plot_list: minVal = 10000 for comp in components: currPPSDCurve = hvsr_data['psd_values_tavg'][comp] if np.nanmin(currPPSDCurve) < minVal: minVal = np.nanmin(currPPSDCurve) results_fig.add_annotation(x=np.log10(hvsr_data['BestPeak'][azimuth]['f0']), y=minVal, text=f"{hvsr_data['BestPeak'][azimuth]['f0']:.3f} Hz", bgcolor='rgba(255, 255, 255, 0.7)', showarrow=False, yref=yaxis_to_use, secondary_y=use_secondary, row=compRow, col=1) # Plot the main averaged component PPSDs for comp in components: results_fig.add_trace(go.Scatter(x=hvsr_data.x_freqs[comp], y=hvsr_data['psd_values_tavg'][comp], line=dict(width=2, dash="solid", color=compColor[comp]),marker=None, name='PPSD Curve '+comp, yaxis=yaxis_to_use), secondary_y=use_secondary, row=compRow, col='all') # If new subplot, update accordingly if compRow==2: results_fig.update_xaxes(type='log', range=[np.log10(hvsr_data['hvsr_band'][0]), np.log10(hvsr_data['hvsr_band'][1])], row=compRow, col=1) return results_fig def parse_spec_plot_list(hv_data, spec_plot_list, subplot_num, azimuth='HV'): hvsr_data = hv_data if azimuth == 'HV': HVCol = 'HV_Curves' else: HVCol = 'HV_Curves_'+azimuth # Initial setup hvsrDF = hvsr_data.hvsr_windows_df specAxisTimes = np.array([dt.isoformat() for dt in hvsrDF.index.to_pydatetime()]) y_data = hvsr_data.x_freqs['Z'][1:] image_data = np.stack(hvsrDF[HVCol]).T maxZ = np.percentile(image_data, 100) minZ = np.percentile(image_data, 0) use_mask = hvsr_data.hvsr_windows_df.Use.values use_mask = np.tile(use_mask, (image_data.shape[0],1)) use_mask = np.where(use_mask is False, np.nan, use_mask) hmap = go.Heatmap(z=image_data, x=specAxisTimes, y=y_data, colorscale='Turbo', showlegend=False, #opacity=0.7, hovertemplate='Time [UTC]: %{x}<br>Frequency [Hz]: %{y:.2f}<br>H/V Amplitude: %{z:.2f}<extra></extra>', zmin=minZ,zmax=maxZ, showscale=False, name='HV Curve Amp. over Time') results_fig.add_trace(hmap, row=subplot_num, col=1) data_used = go.Heatmap( x=specAxisTimes, y=y_data, z=use_mask, showlegend=False, colorscale=[[0, 'rgba(0,0,0,0.66)'], [0.25, 'rgba(0,0,0,0.66)'], [1, 'rgba(250,250,250,0)']], showscale=False, name='Used') results_fig.add_trace(data_used, row=subplot_num, col=1) # tp currently is not being added to spec_plot_list if 'tp' in spec_plot_list: yvals = [] for row in hvsrDF[HVCol].values: maxInd = np.argmax(row) yvals.append(y_data[maxInd]) tp_trace = go.Scatter(x=specAxisTimes, y=yvals, mode='markers', line=None, marker=dict(color='white', size=2, line=dict(color='black', width=0.1)), name='Individual H/V Peaks') results_fig.add_trace(tp_trace, row=subplot_num, col='all') if 'p' in spec_plot_list: results_fig.add_hline(y=hvsr_data['BestPeak'][azimuth]['f0'], line_width=1, line_dash='dash', line_color='black', row=subplot_num, col='all') if 'ann' in spec_plot_list: results_fig.add_annotation(x=specAxisTimes[-1], y=hvsr_data['hvsr_band'][1], text=f"Peak: {hvsr_data['BestPeak'][azimuth]['f0']:.3f} Hz", bgcolor='rgba(255, 255, 255, 0.7)', showarrow=False, xanchor='right', yanchor='top', row=subplot_num, col='all') if 'leg' in spec_plot_list: pass results_fig.update_yaxes(type='log', range=[np.log10(hvsr_data['hvsr_band'][0]), np.log10(hvsr_data['hvsr_band'][1])], row=subplot_num, col=1) results_fig.add_annotation( text=f"{hvsrDF['Use'].astype(bool).sum()}/{hvsrDF.shape[0]} windows used", x=max(specAxisTimes), y=np.log10(min(y_data))+(np.log10(max(y_data))-np.log10(min(y_data)))*0.01, xanchor="right", yanchor="bottom",bgcolor='rgba(256,256,256,0.7)', showarrow=False,row=subplot_num, col=1) return results_fig def update_results_fig(hv_data, plot_string): global results_fig global results_subp hvsr_data = hv_data if isinstance(hvsr_data, sprit_hvsr.HVSRBatch): hvsr_data=hvsr_data[0] hvsrDF = hvsr_data.hvsr_windows_df plot_list = parse_plot_string(plot_string) combinedComp=False noSubplots = 3 - plot_list.count([]) if plot_list[1] != [] and '+' not in plot_list[1][0]: combinedComp = True noSubplots -= 1 # Get all data for each plotted item # COMP Plot # Figure out which subplot is which if combinedComp: comp_plot_row = 1 spec_plot_row = 2 else: comp_plot_row = 2 spec_plot_row = 3 # Re-initialize results_fig results_fig.data = [] results_fig.update_layout(grid=None) # Clear the existing grid layout if not combinedComp: results_subp = subplots.make_subplots(rows=3, cols=1, horizontal_spacing=0.01, vertical_spacing=0.07, row_heights=[2, 1.5, 1]) else: results_subp = subplots.make_subplots(rows=2, cols=1, horizontal_spacing=0.01, vertical_spacing=0.07, specs =[[{'secondary_y': True}], [{'secondary_y': False}]], row_heights=[1, 1]) results_fig.update_layout(grid={'rows': noSubplots}) #del results_fig results_fig = go.FigureWidget(results_subp) results_fig = parse_comp_plot_list(hvsr_data, comp_plot_list=plot_list[1]) # HVSR Plot (plot this after COMP so it is on top COMP and to prevent deletion with no C+) results_fig = parse_hv_plot_list(hvsr_data, hvsr_plot_list=plot_list[0]) # Will always plot the HV Curve results_fig.add_trace(go.Scatter(x=hvsr_data.x_freqs['Z'],y=hvsr_data.hvsr_curve, line={'color':'black', 'width':1.5},marker=None, name='HVSR Curve'), row=1, col='all') # SPEC plot results_fig = parse_spec_plot_list(hvsr_data, spec_plot_list=plot_list[2], subplot_num=spec_plot_row) # Final figure updating showtickLabels = (plot_list[1]==[] or '+' not in plot_list[1][0]) if showtickLabels: side='bottom' else: side='top' results_fig.update_xaxes(type='log', range=[np.log10(hvsr_data['hvsr_band'][0]), np.log10(hvsr_data['hvsr_band'][1])], side='top', row=1, col=1) results_fig.update_xaxes(type='log',overlaying='x', range=[np.log10(hvsr_data['hvsr_band'][0]), np.log10(hvsr_data['hvsr_band'][1])], side='bottom', row=1, col=1) if comp_plot_row!=1: results_fig.update_xaxes(showticklabels=showtickLabels, row=comp_plot_row, col=1) if preview_fig.layout.width is None: if outlier_fig.layout.width is None: chartwidth = 800 else: chartwidth = outlier_fig.layout.width else: chartwidth = preview_fig.layout.width results_fig.update_layout(margin={"l":10, "r":10, "t":35, 'b':0}, showlegend=False, autosize=True, height = 1.2 * float(chartwidth), title=f"{hvsr_data['site']} Results") results_fig.update_yaxes(title_text='H/V Ratio', row=1, col=1) results_fig.update_yaxes(title_text='H/V Over Time', row=noSubplots, col=1) if comp_plot_row==1: results_fig.update_yaxes(title_text="PPSD Amp\n[m2/s4/Hz][dB]", secondary_y=True, row=comp_plot_row, col=1) else: results_fig.update_yaxes(title_text="PPSD Amp\n[m2/s4/Hz][dB]", row=comp_plot_row, col=1) # Reset results_graph_widget and display with results_graph_widget: clear_output(wait=True) display(results_fig) if show_plot_check.value: results_fig.show() sprit_tabs.selected_index = 4 log_textArea.value += f"\n\n{datetime.datetime.now()}\nResults Figure Updated: {plot_string}" process_hvsr_button.on_click(process_data) # PREVIEW TAB #Initialize plot preview_subp = subplots.make_subplots(rows=4, cols=1, shared_xaxes=True, horizontal_spacing=0.01, vertical_spacing=0.01, row_heights=[3,1,1,1]) preview_fig = go.FigureWidget(preview_subp) def update_preview_fig(hv_data, preview_fig): preview_fig.data = [] hvsr_data = hv_data if isinstance(hvsr_data, sprit_hvsr.HVSRBatch): hvsr_data=hvsr_data[0] stream_z = hvsr_data['stream'].select(component='Z') #may be np.ma.masked_array stream_e = hvsr_data['stream'].select(component='E') #may be np.ma.masked_array stream_n = hvsr_data['stream'].select(component='N') #may be np.ma.masked_array # Get iso_times and datetime.datetime utcdt = stream_z[0].times(type='utcdatetime') iso_times=[] dt_times = [] for t in utcdt: if t is not np.ma.masked: iso_times.append(t.isoformat()) dt_times.append(datetime.datetime.fromisoformat(t.isoformat())) else: iso_times.append(np.nan) iso_times=np.array(iso_times) dt_times = np.array (dt_times) # Generate spectrogram f, t, Sxx = signal.spectrogram(x=stream_z[0].data, fs=stream_z[0].stats.sampling_rate, mode='magnitude') # Get times for the axis (one time per window) axisTimes = [] for tpass in t: axisTimes.append((dt_times[0]+datetime.timedelta(seconds=tpass)).isoformat()) # Add data to preview_fig # Add spectrogram of Z component minz = np.percentile(Sxx, 1) maxz = np.percentile(Sxx, 99) hmap = go.Heatmap(z=Sxx, x=axisTimes, y=f, colorscale='Turbo', showlegend=False, hovertemplate='Time [UTC]: %{x}<br>Frequency [Hz]: %{y:.2f}<br>Spectrogram Magnitude: %{z:.2f}<extra></extra>', zmin=minz, zmax=maxz, showscale=False, name='Z Component Spectrogram') preview_fig.add_trace(hmap, row=1, col=1) preview_fig.update_yaxes(type='log', range=[np.log10(hvsr_data['hvsr_band'][0]), np.log10(hvsr_data['hvsr_band'][1])], row=1, col=1) preview_fig.update_yaxes(title={'text':'Spectrogram (Z)'}, row=1, col=1) # Add raw traces dec_factor=5 #This just makes the plotting go faster, by "decimating" the data preview_fig.add_trace(go.Scatter(x=iso_times[::dec_factor], y=stream_z[0].data[::dec_factor], line={'color':'black', 'width':0.5},marker=None, name='Z component data'), row=2, col='all') preview_fig.update_yaxes(title={'text':'Z'}, row=2, col=1) preview_fig.add_trace(go.Scatter(x=iso_times[::dec_factor], y=stream_e[0].data[::dec_factor], line={'color':'blue', 'width':0.5},marker=None, name='E component data'),row=3, col='all') preview_fig.update_yaxes(title={'text':'E'}, row=3, col=1) preview_fig.add_trace(go.Scatter(x=iso_times[::dec_factor], y=stream_n[0].data[::dec_factor], line={'color':'red', 'width':0.5},marker=None, name='N component data'), row=4, col='all') preview_fig.update_yaxes(title={'text':'N'}, row=4, col=1) #preview_fig.add_trace(p) preview_fig.update_layout(margin={"l":10, "r":10, "t":30, 'b':0}, showlegend=False, title=f"{hvsr_data['site']} Data Preview") if show_plot_check.value: preview_fig.show() # REMOVE NOISE SUBTAB # STA/LTA Antitrigger stalta_check = widgets.Checkbox(value=False, disabled=False, indent=False, description='STA/LTA Antitrigger') sta = widgets.FloatText(description='STA [s]', style={'description_width': 'initial'}, placeholder=5, value=5,layout=widgets.Layout(height='auto', width='auto')) lta = widgets.FloatText(description='LTA [s]', style={'description_width': 'initial'}, placeholder=30, value=30,layout=widgets.Layout(height='auto', width='auto')) stalta_thresh_low = widgets.FloatText(description='STA/LTA Thresholds (low, high)', style={'description_width': 'initial'}, placeholder=0.5, value=0.5,layout=widgets.Layout(height='auto', width='auto')) stalta_thresh_hi = widgets.FloatText(style={'description_width': 'initial'}, placeholder=5, value=5,layout=widgets.Layout(height='auto', width='auto')) #% Saturation Threshold max_saturation_check = widgets.Checkbox(description='Percentage Threshold (Instantaneous)', value=False, disabled=False, indent=False) max_saturation_pct = widgets.FloatText(description='Max Saturation %:', style={'description_width': 'initial'}, placeholder=0.995, value=0.995,layout=widgets.Layout(height='auto', width='auto')) #Noise Windows noisy_windows_check = widgets.Checkbox(description='Noisy Windows', value=False, disabled=False, indent=False) max_window_pct = widgets.FloatText(description='Max Window %:', style={'description_width': 'initial'}, placeholder=0.8, value=0.8,layout=widgets.Layout(height='auto', width='auto')) noisy_window_length = widgets.FloatText(description='Window Length [s]:', style={'description_width': 'initial'}, placeholder=30, value=30,layout=widgets.Layout(height='auto', width='auto')) #Warmup/cooldown warmcool_check = widgets.Checkbox(description='Warmup & Cooldown Time', value=False, disabled=False, indent=False) warmup_time = widgets.FloatText(description='Warmup time [s]:', style={'description_width': 'initial'}, placeholder=0, value=0,layout=widgets.Layout(height='auto', width='auto')) cooldown_time = widgets.FloatText(description='Cooldown time [s]:', style={'description_width': 'initial'}, placeholder=0, value=0,layout=widgets.Layout(height='auto', width='auto')) #STD Ratio std_ratio_check = widgets.Checkbox(description='Standard Deviation Antitrigger (not yet implemented)', value=False, disabled=True, indent=False) std_ratio_text = widgets.FloatText(description='StdDev Ratio:', style={'description_width': 'initial'}, placeholder=0, value=0,layout=widgets.Layout(height='auto', width='auto'), disabled=True) std_window_length_text = widgets.FloatText(description='Moving window Length [s]:', style={'description_width': 'initial'}, placeholder=0, value=0,layout=widgets.Layout(height='auto', width='auto'),disabled=True) #Autoremove auto_remove_check = widgets.Checkbox(description='Use Auto Remove', value=False, disabled=False, indent=False) #Remove from raw data raw_data_remove_check = widgets.Checkbox(description='Remove Noise From Raw Data', value=False, disabled=False, indent=False) #remove_noise call remove_noise_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'remove_noise' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) remove_noise_call = widgets.HTML(value='()') remove_noise_call_hbox = widgets.HBox([remove_noise_prefix, remove_noise_call]) # Update remove_outlier call def update_remove_noise_call(): rnkwargs = get_remove_noise_kwargs() rn_text = f"""(hvsr_data=hvsr_data, remove_method={rnkwargs['remove_method']}, sat_percent={rnkwargs['sat_percent']}, noise_percent={rnkwargs['noise_percent']}, sta={rnkwargs['sta']}, lta={rnkwargs['lta']}, stalta_thresh={rnkwargs['stalta_thresh']}, warmup_time={rnkwargs['warmup_time']}, cooldown_time={rnkwargs['cooldown_time']}, min_win_size={rnkwargs['min_win_size']}, remove_raw_noise={rnkwargs['remove_raw_noise']}, verbose={verbose_check.value})""" remove_noise_call.value='<style>p {word-wrap: break-word}</style> <p>' + rn_text + '</p>' update_remove_noise_call() #Update noise windows update_noise_windows_button = widgets.Button(description='Update Noise Windows',button_style='info',layout=widgets.Layout(height='auto', width='auto'), disabled=True) preview_graph_widget = widgets.Output() #progress bar (same as above) preview_progress_hbox = widgets.HBox(children=[progress_bar, update_noise_windows_button, process_hvsr_button]) # Add it all in to the tab stalta_hbox = widgets.HBox([stalta_check, sta, lta, stalta_thresh_low, stalta_thresh_hi]) sat_hbox = widgets.HBox([max_saturation_check, max_saturation_pct]) noise_win_hbox = widgets.HBox([noisy_windows_check, max_window_pct, noisy_window_length]) warmcool_hbox = widgets.HBox([warmcool_check, warmup_time, cooldown_time]) std_ratio_hbox = widgets.HBox([std_ratio_check, std_ratio_text, std_window_length_text]) spacer_hbox = widgets.HBox([tenpct_spacer]) preview_noise_tab = widgets.VBox([stalta_hbox, sat_hbox, noise_win_hbox, warmcool_hbox, std_ratio_hbox, auto_remove_check, raw_data_remove_check, spacer_hbox, remove_noise_call_hbox]) preview_graph_tab = widgets.VBox(children=[preview_graph_widget]) preview_subtabs = widgets.Tab([preview_graph_tab, preview_noise_tab]) preview_tab = widgets.VBox() preview_subtabs.set_title(0, "Data Preview") preview_subtabs.set_title(1, "Noise Removal") preview_tab.children = [preview_subtabs, preview_progress_hbox] # Initialize tab with preview_graph_widget: display(preview_fig) # SETTINGS TAB plot_settings_tab = widgets.GridspecLayout(18, ui_width) settings_progress_hbox = widgets.HBox(children=[progress_bar, tenpct_spacer, process_hvsr_button]) # PPSD SETTINGS SUBTAB ppsd_length_label = widgets.Label(value='Window Length for PPSDs:') ppsd_length = widgets.FloatText(style={'description_width': 'initial'}, placeholder=20, value=20,layout=widgets.Layout(height='auto', width='auto'), disabled=False) overlap_pct_label = widgets.Label(value='Overlap %:') overlap_pct = widgets.FloatText(style={'description_width': 'initial'}, placeholder=0.5, value=0.5, layout=widgets.Layout(height='auto', width='auto'), disabled=False) period_step_label = widgets.Label(value='Period Step Octaves:') period_step_octave = widgets.FloatText(style={'description_width': 'initial'}, placeholder=0.0625, value=0.0625, layout=widgets.Layout(height='auto', width='auto'), disabled=False) skip_on_gaps_label = widgets.Label(value='Skip on gaps:') skip_on_gaps = widgets.Checkbox(value=False, disabled=False, indent=False) db_step_label = widgets.Label(value='dB bins:') db_bins_min = widgets.FloatText(description='Min. dB', style={'description_width': 'initial'}, placeholder=-200, value=-200, layout=widgets.Layout(height='auto', width='auto'), disabled=False) db_bins_max = widgets.FloatText(description='Max. dB', style={'description_width': 'initial'}, placeholder=-50, value=-50, layout=widgets.Layout(height='auto', width='auto'), disabled=False) db_bins_step = widgets.FloatText(description='dB Step', style={'description_width': 'initial'}, placeholder=1, value=1, layout=widgets.Layout(height='auto', width='auto'), disabled=False) period_limit_label = widgets.Label(value='Period Limits:') minPLim = round(1/(hvsr_band_max_box.value), 3) maxPLim = round(1/(hvsr_band_min_box.value), 3) period_limits_min = widgets.FloatText(description='Min. Period Limit', style={'description_width': 'initial'}, placeholder=minPLim, value=minPLim, layout=widgets.Layout(height='auto', width='auto'), disabled=False) period_limits_max = widgets.FloatText(description='Max. Period Limit', style={'description_width': 'initial'}, placeholder=maxPLim, value=maxPLim, layout=widgets.Layout(height='auto', width='auto'), disabled=False) period_smoothing_width = widgets.FloatText(description='Period Smoothing Width', style={'description_width': 'initial'}, placeholder=1, value=1, layout=widgets.Layout(height='auto', width='auto'), disabled=False) special_handling_dropdown = widgets.Dropdown(description='Special Handling', value='none', options=[('None', 'none'), ('Ringlaser', 'ringlaser'), ('Hydrophone', 'hydrophone')], style={'description_width': 'initial'}, layout=widgets.Layout(height='auto', width='auto'), disabled=False) #remove_noise call generate_ppsd_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'generate_psds' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) generate_ppsd_call = widgets.HTML(value='()') generate_ppsd_call_hbox = widgets.HBox([generate_ppsd_prefix, generate_ppsd_call]) # Update generate_psds() call def update_generate_ppsd_call(): gppsdkwargs = get_generate_ppsd_kwargs() gppsd_text = f"""(hvsr_data=hvsr_data, stats=hvsr_data['stream'].select(component='*').traces[0].stats, metadata=hvsr_data['paz']['*'], skip_on_gaps={gppsdkwargs['skip_on_gaps']}, db_bins={gppsdkwargs['db_bins']}, ppsd_length={gppsdkwargs['ppsd_length']}, overlap={gppsdkwargs['overlap']}, special_handling={gppsdkwargs['special_handling']}, period_smoothing_width_octaves={gppsdkwargs['period_smoothing_width_octaves']}, period_step_octaves={gppsdkwargs['period_step_octaves']}, period_limits={gppsdkwargs['period_limits']}, verbose={verbose_check.value})""" generate_ppsd_call.value='<style>p {word-wrap: break-word}</style> <p>' + gppsd_text + '</p>' update_generate_ppsd_call() ppsd_length_hbox = widgets.HBox([ppsd_length_label, ppsd_length]) overlap_pct_hbox = widgets.HBox([overlap_pct_label, overlap_pct]) pstep_hbox = widgets.HBox([period_step_label, period_step_octave]) skipgaps_hbox = widgets.HBox([skip_on_gaps_label, skip_on_gaps]) db_bins_hbox = widgets.HBox([db_step_label, db_bins_min, db_bins_max, db_bins_step]) plim_hbox = widgets.HBox([period_limit_label, period_limits_min, period_limits_max, period_smoothing_width]) ppsd_settings_tab = widgets.VBox([ppsd_length_hbox, overlap_pct_hbox, pstep_hbox, skipgaps_hbox, db_bins_hbox, plim_hbox, special_handling_dropdown, generate_ppsd_call_hbox]) # OUTLIER SETTINGS SUBTAB rmse_pctile_check = widgets.Checkbox(description='Using percentile', layout=widgets.Layout(height='auto', width='auto'), style={'description_width': 'initial'}, value=True) rmse_thresh = widgets.FloatText(description='RMSE Threshold', style={'description_width': 'initial'}, placeholder=98, value=98, layout=widgets.Layout(height='auto', width='auto'), disabled=False) use_hv_curve_rmse = widgets.Checkbox(description='Use HV Curve Outliers (may only be used after they have been calculated during the process_hvsr() step))', layout=widgets.Layout(height='auto', width='auto'), style={'description_width': 'initial'}, value=False, disabled=True) outlier_threshbox_hbox = widgets.HBox(children=[rmse_thresh, rmse_pctile_check]) outlier_params_vbox = widgets.VBox(children=[outlier_threshbox_hbox, use_hv_curve_rmse]) global outlier_fig outlier_fig = go.FigureWidget() outlier_graph_widget = widgets.Output() outlier_thresh_slider_label = widgets.Label(value='RMSE Thresholds:') rmse_thresh_slider = widgets.FloatSlider(value=0, min=0, max=100, step=0.1,description='RMSE Value',layout=widgets.Layout(height='auto', width='auto'),disabled=True) rmse_pctile_slider = widgets.FloatSlider(value=get_default(sprit_hvsr.remove_outlier_curves, 'rmse_thresh'), min=0, max=100, step=0.1, description="Percentile",layout=widgets.Layout(height='auto', width='auto'),) def calc_rmse(array_2d): medArray = np.nanmedian(array_2d, axis=0) rmse = np.sqrt(((np.subtract(array_2d, medArray)**2).sum(axis=1))/array_2d.shape[1]) return rmse def on_update_rmse_thresh_slider(change): if use_hv_curve_rmse.value: rmse = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['HV_Curves'])) else: rmsez = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['psd_values_Z'])) rmsee = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['psd_values_E'])) rmsen = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['psd_values_N'])) rmse = np.stack([rmsez, rmsee, rmsen]).flatten() if rmse_pctile_check.value: rmse_thresh.value = rmse_pctile_slider.value else: rmse_thresh.value = rmse_thresh_slider.value rmse_pctile_slider.value = ((rmse < rmse_thresh_slider.value).sum() / len(rmse)) * 100 def on_update_rmse_pctile_slider(change): if use_hv_curve_rmse.value: rmse = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['HV_Curves'])) else: rmsez = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['psd_values_Z'])) rmsee = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['psd_values_E'])) rmsen = calc_rmse(np.stack(hvsr_data.hvsr_windows_df['psd_values_N'])) rmse = np.stack([rmsez, rmsee, rmsen]) if rmse_pctile_check.value: rmse_thresh_slider.value = np.percentile(rmse, rmse_pctile_slider.value) rmse_thresh.value = rmse_pctile_slider.value else: rmse_thresh.value = rmse_thresh_slider.value def on_update_rmse_pctile_check(change): if rmse_pctile_check.value: rmse_pctile_slider.disabled = False rmse_thresh_slider.disabled = True else: rmse_pctile_slider.disabled = True rmse_thresh_slider.disabled = False def on_update_rmse_thresh(change): if rmse_pctile_check.value: rmse_pctile_slider.value = rmse_thresh.value else: rmse_thresh_slider.value = rmse_thresh.value rmse_pctile_check.observe(on_update_rmse_pctile_check) rmse_thresh_slider.observe(on_update_rmse_thresh_slider) rmse_pctile_slider.observe(on_update_rmse_pctile_slider) rmse_thresh.observe(on_update_rmse_thresh) use_hv_curve_label = widgets.Label(value='NOTE: Outlier curves may only be identified after PPSDs have been calculated (during the generate_psds() step)', layout=widgets.Layout(height='auto', width='80%')) generate_ppsd_button = widgets.Button(description='Generate PPSDs', layout=widgets.Layout(height='auto', width='20%', justify_content='flex-end'), disabled=False) update_outlier_plot_button = widgets.Button(description='Remove Outliers', layout=widgets.Layout(height='auto', width='20%', justify_content='flex-end'), disabled=False) outlier_ppsd_hbox = widgets.HBox([use_hv_curve_label, generate_ppsd_button, update_outlier_plot_button]) remove_outlier_curve_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'remove_outlier_curves' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) remove_outlier_curve_call = widgets.HTML(value='()') remove_outlier_hbox = widgets.HBox([remove_outlier_curve_prefix, remove_outlier_curve_call]) # Update remove_outlier call def update_remove_outlier_curve_call(): roc_text = f"""(hvsr_data=hvsr_data, rmse_thresh={rmse_thresh.value}, use_percentile={rmse_pctile_check.value}, use_hv_curve={use_hv_curve_rmse.value}...verbose={verbose_check.value})""" remove_outlier_curve_call.value='<style>p {word-wrap: break-word}</style> <p>' + roc_text + '</p>' update_remove_outlier_curve_call() def update_outlier_fig_button(button): outlier_fig, hvsr_data = update_outlier_fig(button) generate_ppsd_button.on_click(process_data) update_outlier_plot_button.on_click(update_outlier_fig_button) outlier_settings_tab = widgets.VBox(children=[outlier_params_vbox, outlier_graph_widget, outlier_thresh_slider_label, rmse_thresh_slider, rmse_pctile_slider, outlier_ppsd_hbox, remove_outlier_hbox]) with outlier_graph_widget: display(outlier_fig) def update_outlier_fig(input=None, _rmse_thresh=rmse_pctile_slider.value, _use_percentile=True, _use_hv_curve=use_hv_curve_rmse.value, _verbose=verbose_check.value): global outlier_fig global hvsr_data hv_data = hvsr_data roc_kwargs = {'rmse_thresh':rmse_pctile_slider.value, 'use_percentile':True, 'use_hv_curve':use_hv_curve_rmse.value, 'plot_engine':'plotly', 'show_plot':False, 'verbose':verbose_check.value } if 'PPSDStatus' in hvsr_data.ProcessingStatus.keys() and hvsr_data.ProcessingStatus['PPSDStatus']: log_textArea.value += f"\n\n{datetime.datetime.now()}\nremove_outlier_curves():\n'{roc_kwargs}" hvsr_data = sprit_hvsr.remove_outlier_curves(hvsr_data, **roc_kwargs) else: log_textArea.value += f"\n\n{datetime.datetime.now()}\nremove_outlier_curves() attempted, but not completed. hvsr_data.ProcessingStatus['PPSDStatus']=False\n'{roc_kwargs}" return outlier_fig, hvsr_data if roc_kwargs['use_hv_curve']: no_subplots = 1 if hasattr(hvsr_data, 'hvsr_windows_df') and 'HV_Curves' in hvsr_data.hvsr_windows_df.columns: outlier_fig.data = [] outlier_fig.update_layout(grid=None) # Clear the existing grid layout outlier_subp = subplots.make_subplots(rows=no_subplots, cols=1, horizontal_spacing=0.01, vertical_spacing=0.1) outlier_fig.update_layout(grid={'rows': 1}) outlier_fig = go.FigureWidget(outlier_subp) x_data = hvsr_data['x_freqs'] curve_traces = [] for hv in hvsr_data.hvsr_windows_df['HV_Curves'].iterrows(): curve_traces.append(go.Scatter(x=x_data, y=hv[1])) outlier_fig.add_traces(curve_traces) # Calculate a median curve, and reshape so same size as original medCurve = np.nanmedian(np.stack(hvsr_data.hvsr_windows_df['HV_Curves']), axis=0) outlier_fig.add_trace(go.Scatter(x=x_data, y=medCurve, line=dict(color='rgba(0,0,0,1)', width=1.5),showlegend=False)) minY = np.nanmin(np.stack(hvsr_data.hvsr_windows_df['HV_Curves'])) maxY = np.nanmax(np.stack(hvsr_data.hvsr_windows_df['HV_Curves'])) totalWindows = hvsr_data.hvsr_windows_df.shape[0] #medCurveArr = np.tile(medCurve, (curr_data.shape[0], 1)) else: no_subplots = 3 outlier_fig.data = [] outlier_fig.update_layout(grid=None) # Clear the existing grid layout outlier_subp = subplots.make_subplots(rows=no_subplots, cols=1, horizontal_spacing=0.01, vertical_spacing=0.02, row_heights=[1, 1, 1]) outlier_fig.update_layout(grid={'rows': 3}) outlier_fig = go.FigureWidget(outlier_subp) if hasattr(hvsr_data, 'hvsr_windows_df'): rowDict = {'Z':1, 'E':2, 'N':3} showTLabelsDict={'Z':False, 'E':False, 'N':True} def comp_rgba(comp, a): compstr = '' if comp=='Z': compstr = f'rgba(0, 0, 0, {a})' if comp=='E': compstr = f'rgba(50, 50, 250, {a})' if comp=='N': compstr = f'rgba(250, 50, 50, {a})' return compstr compNames = ['Z', 'E', 'N'] rmse_to_plot=[] med_traces=[] noRemoved = 0 indRemoved = [] for i, comp in enumerate(compNames): if hasattr(hvsr_data, 'x_freqs'): x_data = hvsr_data['x_freqs'][comp] else: x_data = [1/p for p in hvsr_data['ppsds'][comp]['period_xedges'][1:]] column = 'psd_values_'+comp # Retrieve data from dataframe (use all windows, just in case) curr_data = np.stack(hvsr_data['hvsr_windows_df'][column]) # Calculate a median curve, and reshape so same size as original medCurve = np.nanmedian(curr_data, axis=0) medCurveArr = np.tile(medCurve, (curr_data.shape[0], 1)) medTrace = go.Scatter(x=x_data, y=medCurve, line=dict(color=comp_rgba(comp, 1), width=1.5), name=f'{comp} Component', showlegend=True) # Calculate RMSE rmse = np.sqrt(((np.subtract(curr_data, medCurveArr)**2).sum(axis=1))/curr_data.shape[1]) rmse_threshold = np.percentile(rmse, roc_kwargs['rmse_thresh']) # Retrieve index of those RMSE values that lie outside the threshold timeIndex = hvsr_data['hvsr_windows_df'].index for j, curve in enumerate(curr_data): if rmse[j] > rmse_threshold: badTrace = go.Scatter(x=x_data, y=curve, line=dict(color=comp_rgba(comp, 1), width=1.5, dash='dash'), #marker=dict(color=comp_rgba(comp, 1), size=3), name=str(hvsr_data.hvsr_windows_df.index[j]), showlegend=False) outlier_fig.add_trace(badTrace, row=rowDict[comp], col=1) if j not in indRemoved: indRemoved.append(j) noRemoved += 1 else: goodTrace = go.Scatter(x=x_data, y=curve, line=dict(color=comp_rgba(comp, 0.01)), name=str(hvsr_data.hvsr_windows_df.index[j]), showlegend=False) outlier_fig.add_trace(goodTrace, row=rowDict[comp], col=1) timeIndRemoved = pd.DatetimeIndex([timeIndex[ind] for ind in indRemoved]) hvsr_data['hvsr_windows_df'].loc[timeIndRemoved, 'Use'] = False outlier_fig.add_trace(medTrace, row=rowDict[comp], col=1) outlier_fig.update_xaxes(showticklabels=False, row=1, col=1) outlier_fig.update_yaxes(title={'text':'Z'}, row=1, col=1) outlier_fig.update_xaxes(showticklabels=False, row=2, col=1) outlier_fig.update_yaxes(title={'text':'E'}, row=2, col=1) outlier_fig.update_xaxes(showticklabels=True, row=3, col=1) outlier_fig.update_yaxes(title={'text':'N'}, row=3, col=1) outlier_fig.update_layout(margin={"l":10, "r":10, "t":30, 'b':0}, showlegend=True, title=f"{hvsr_data['site']} Outliers") if comp == 'N': minY = np.nanmin(curr_data) maxY = np.nanmax(curr_data) totalWindows = curr_data.shape[0] outlier_fig.add_annotation( text=f"{len(indRemoved)}/{totalWindows} outlier windows removed", x=np.log10(max(x_data)) - (np.log10(max(x_data))-np.log10(min(x_data))) * 0.01, y=minY+(maxY-minY)*0.01, xanchor="right", yanchor="bottom",#bgcolor='rgba(256,256,256,0.7)', showarrow=False,row=no_subplots, col=1) outlier_fig.update_xaxes(type='log') with outlier_graph_widget: clear_output(wait=True) display(outlier_fig) if show_plot_check.value: outlier_fig.show() return outlier_fig, hvsr_data # HVSR SETTINGS SUBTAB h_combine_meth = widgets.Dropdown(description='Horizontal Combination Method', value=3, options=[('1. Differential Field Assumption (not implemented)', 1), ('2. Arithmetic Mean | H = (N + E)/2', 2), ('3. Geometric Mean | H = √(N * E) (SESAME recommended)', 3), ('4. Vector Summation | H = √(N^2 + E^2)', 4), ('5. Quadratic Mean | H = √(N^2 + E^2)/2', 5), ('6. Maximum Horizontal Value | H = max(N, E)', 6)], style={'description_width': 'initial'}, layout=widgets.Layout(height='auto', width='auto'), disabled=False) freq_smoothing = widgets.Dropdown(description='Frequency Smoothing Operations', value='konno ohmachi', options=[('Konno-Ohmachi', 'konno ohmachi'), ('Constant','constant'), ('Proportional', 'proportional'), ('None', None)], style={'description_width': 'initial'}, layout=widgets.Layout(height='auto', width='auto'), disabled=False) freq_smooth_width = widgets.FloatText(description='Freq. Smoothing Width', style={'description_width': 'initial'}, placeholder=40, value=40, layout=widgets.Layout(height='auto', width='auto'), disabled=False) resample_hv_curve_bool = widgets.Checkbox(layout=widgets.Layout(height='auto', width='auto'), style={'description_width': 'initial'}, value=True) resample_hv_curve = widgets.IntText(description='Resample H/V Curve', style={'description_width': 'initial'}, placeholder=500, value=500, layout=widgets.Layout(height='auto', width='auto'), disabled=False) smooth_hv_curve_bool = widgets.Checkbox(layout=widgets.Layout(height='auto', width='auto'), style={'description_width': 'initial'}, value=True) smooth_hv_curve = widgets.IntText(description='Smooth H/V Curve', style={'description_width': 'initial'}, placeholder=51, value=51, layout=widgets.Layout(height='auto', width='auto'), disabled=False) hvsr_band_hbox_hvsrSet = widgets.HBox([hvsr_band_min_box, hvsr_band_max_box],layout=widgets.Layout(height='auto', width='auto')) peak_freq_range_hbox_hvsrSet = widgets.HBox([peak_freq_range_min_box, peak_freq_range_max_box],layout=widgets.Layout(height='auto', width='auto')) peak_selection_type = widgets.Dropdown(description='Peak Selection Method', value='max', options=[('Highest Peak', 'max'), ('Best Scored','scored')], style={'description_width': 'initial'}, layout=widgets.Layout(height='auto', width='auto'), disabled=False) process_hvsr_call_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'process_hvsr' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end', align_content='flex-start')) process_hvsr_call = widgets.HTML(value='()') process_hvsr_call_hbox = widgets.HBox([process_hvsr_call_prefix, process_hvsr_call]) # Update process_hvsr call def update_process_hvsr_call(): ph_kwargs = get_process_hvsr_kwargs() ph_text = f"""(hvsr_data=hvsr_data, method={ph_kwargs['method']}, smooth={ph_kwargs['smooth']}, freq_smooth={ph_kwargs['freq_smooth']}, f_smooth_width={ph_kwargs['f_smooth_width']}, resample={ph_kwargs['resample']}, outlier_curve_rmse_percentile={ph_kwargs['outlier_curve_rmse_percentile']}, verbose={verbose_check.value})""" process_hvsr_call.value='<style>p {word-wrap: break-word}</style> <p>' + ph_text + '</p>' update_process_hvsr_call() check_peaks_call_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>'+'check_peaks' + '</p>', layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) check_peaks_call = widgets.HTML(value='()') check_peaks_call_hbox = widgets.HBox([check_peaks_call_prefix, check_peaks_call]) # Update process_hvsr call def update_check_peaks_call(): cp_kwargs = get_check_peaks_kwargs() cp_text = f"""(hvsr_data=hvsr_data, hvsr_band={cp_kwargs['hvsr_band']}, peak_selection={cp_kwargs['peak_selection']}, peak_freq_range={cp_kwargs['peak_freq_range']}, verbose={verbose_check.value})""" check_peaks_call.value='<style>p {word-wrap: break-word}</style> <p>' + cp_text + '</p>' update_check_peaks_call() freq_smooth_hbox = widgets.HBox([freq_smoothing, freq_smooth_width]) resample_hbox = widgets.HBox([resample_hv_curve_bool, resample_hv_curve]) smooth_hbox = widgets.HBox([smooth_hv_curve_bool, smooth_hv_curve]) # Set up vbox for hvsr_settings subtab hvsr_settings_tab = widgets.VBox([h_combine_meth, freq_smooth_hbox, resample_hbox, smooth_hbox, hvsr_band_hbox_hvsrSet, peak_freq_range_hbox_hvsrSet, peak_selection_type, process_hvsr_call_hbox, check_peaks_call_hbox]) # PLOT SETTINGS SUBTAB hv_plot_label = widgets.Label(value='HVSR Plot', layout=widgets.Layout(height='auto', width='auto', justify_content='center')) component_plot_label = widgets.Label(value='Component Plot', layout=widgets.Layout(height='auto', width='auto', justify_content='center')) spec_plot_label = widgets.Label(value='Spectrogram Plot', layout=widgets.Layout(height='auto', width='auto', justify_content='center')) use_plot_label = widgets.Label(value='Use Plot', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) use_plot_hv = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) use_plot_comp = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) use_plot_spec = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) comibne_plot_label = widgets.Label(value='Combine HV and Comp. Plot', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) combine_hv_comp = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_peak_label = widgets.Label(value='Show Best Peak', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) show_best_peak_hv = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_best_peak_comp = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_best_peak_spec = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) annotate_peak_label = widgets.Label(value='Annotate Best Peak', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) ann_best_peak_hv = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) ann_best_peak_comp = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) ann_best_peak_spec = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_all_peaks_label = widgets.Label(value='Show All Peaks', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) show_all_peaks_hv = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_all_curves_label = widgets.Label(value='Show All Curves', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) show_all_curves_hv = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_all_curves_comp = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_ind_peaks_label = widgets.Label(value='Show Individual Peaks', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) show_ind_peaks_hv = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_ind_peaks_spec = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_std_label = widgets.Label(value='Show Standard Deviation', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) show_std_hv = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_std_comp = widgets.Checkbox(value=True, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_legend_label = widgets.Label(value='Show Legend', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) show_legend_hv = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_legend_comp = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) show_legend_spec = widgets.Checkbox(value=False, layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center'), style={'description_width': 'initial'}) x_type_label = widgets.Label(value='X Type', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) x_type = widgets.Dropdown(options=[('Frequency', 'freq'), ('Period', 'period')], layout=widgets.Layout(height='auto', width='auto'), style={'description_width': 'initial'}) plotly_kwargs_label = widgets.Label(value='Plotly Kwargs', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) plotly_kwargs = widgets.Text(style={'description_width': 'initial'}, layout=widgets.Layout(height='auto', width='auto'), disabled=False) mpl_kwargs_label = widgets.Label(value='Matplotlib Kwargs', layout=widgets.Layout(height='auto', width='auto', justify_content='flex-end', align_items='center')) mpl_kwargs = widgets.Text(style={'description_width': 'initial'}, layout=widgets.Layout(height='auto', width='auto'), disabled=False) plot_hvsr_call = widgets.Label(value=f"Plot String: '{get_default(sprit_hvsr.get_report, 'plot_type')}'") def update_plot_string(): plot_hvsr_text = f"""Plot String: {get_get_report_kwargs()['plot_type']}""" plot_hvsr_call.value = plot_hvsr_text update_plot_string() update_plot_button = widgets.Button(description='Update Plot',button_style='info',layout=widgets.Layout(height='auto', width='auto')) def manually_update_results_fig(change): plot_string = get_get_report_kwargs()['plot_type'] update_results_fig(hvsr_results, plot_string) sprit_tabs.selected_index = 4 # Set up grid for ppsd_settings subtab plot_settings_tab[0, 5:10] = hv_plot_label plot_settings_tab[0, 10:15] = component_plot_label plot_settings_tab[0, 15:] = spec_plot_label plot_settings_tab[1, :] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) plot_settings_tab[2, :5] = use_plot_label plot_settings_tab[2, 5:10] = use_plot_hv plot_settings_tab[2, 10:15] = use_plot_comp plot_settings_tab[2, 15:] = use_plot_spec plot_settings_tab[3, :] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) plot_settings_tab[4, :5] = comibne_plot_label plot_settings_tab[4, 10:15] = combine_hv_comp plot_settings_tab[5, :5] = show_peak_label plot_settings_tab[5, 5:10] = show_best_peak_hv plot_settings_tab[5, 10:15] = show_best_peak_comp plot_settings_tab[5, 15:] = show_best_peak_spec plot_settings_tab[6, :5] = annotate_peak_label plot_settings_tab[6, 5:10] = ann_best_peak_hv plot_settings_tab[6, 10:15] = ann_best_peak_comp plot_settings_tab[6, 15:] = ann_best_peak_spec plot_settings_tab[7, :5] = show_all_peaks_label plot_settings_tab[7, 5:10] = show_all_peaks_hv plot_settings_tab[8, :5] = show_all_curves_label plot_settings_tab[8, 5:10] = show_all_curves_hv plot_settings_tab[8, 10:15] = show_all_curves_comp plot_settings_tab[9, :5] = show_ind_peaks_label plot_settings_tab[9, 5:10] = show_ind_peaks_hv plot_settings_tab[9, 15:] = show_ind_peaks_spec plot_settings_tab[10, :5] = show_std_label plot_settings_tab[10, 5:10] = show_std_hv plot_settings_tab[10, 10:15] = show_std_comp plot_settings_tab[11, :5] = show_legend_label plot_settings_tab[11, 5:10] = show_legend_hv plot_settings_tab[11, 10:15] = show_legend_comp plot_settings_tab[11, 15:] = show_legend_spec plot_settings_tab[12, :] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) plot_settings_tab[13, :5] = x_type_label plot_settings_tab[13, 6:] = x_type plot_settings_tab[14, :5] = plotly_kwargs_label plot_settings_tab[14, 6:] = plotly_kwargs plot_settings_tab[15, :5] = mpl_kwargs_label plot_settings_tab[15, 6:] = mpl_kwargs plot_settings_tab[16, :] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) plot_settings_tab[17, :18] = plot_hvsr_call plot_settings_tab[17, 18:] = update_plot_button update_plot_button.on_click(manually_update_results_fig) # Place everything in Settings Tab settings_subtabs = widgets.Tab([ppsd_settings_tab, hvsr_settings_tab, outlier_settings_tab, plot_settings_tab]) settings_tab = widgets.VBox(children=[settings_subtabs, settings_progress_hbox]) settings_subtabs.set_title(0, "PPSD Settings") settings_subtabs.set_title(1, "HVSR Settings") settings_subtabs.set_title(2, "Outlier Settings") settings_subtabs.set_title(3, "Plot Settings") # LOG TAB - not currently using log_tab = widgets.VBox(children=[log_textArea]) #log_textArea = widgets.Textarea(value="SESSION LOG", disabled=True, layout={'height': '99%','width': '99%', 'overflow': 'scroll'}) # RESULTS TAB # PLOT SUBTAB global results_subp results_subp = subplots.make_subplots(rows=3, cols=1, horizontal_spacing=0.01, vertical_spacing=0.01, row_heights=[2,1,1]) results_fig = go.FigureWidget(results_subp) global results_graph_widget results_graph_widget = widgets.Output() with results_graph_widget: display(results_fig) global printed_results_textArea printed_results_textArea = widgets.Textarea(value="RESULTS", disabled=True, layout={'height': '500px','width': '99%', 'overflow': 'scroll'}) global results_table initialTableCols=['SiteName', 'Acq_Date', 'Longitude', 'Latitude', 'Elevation', 'PeakFrequency', 'WindowLengthFreq.', 'SignificantCycles', 'LowCurveStDevOverTime', 'PeakProminenceBelow', 'PeakProminenceAbove', 'PeakAmpClarity', 'FreqStability', 'PeakStability_FreqStD', 'PeakStability_AmpStD', 'PeakPasses'] results_table = widgets.HTML(value=pd.DataFrame(columns=initialTableCols).to_html()) # A text box labeled Data Filepath export_results_table_filepath = widgets.Text(description='Export Filepath:', placeholder='', value='', style={'description_width': 'initial'},layout=widgets.Layout(width='90%')) export_results_table_read_button = widgets.Button(description='', icon='fa-file-import',button_style='success', layout=widgets.Layout(width='10%')) export_results_table_browse_button = widgets.Button(description='Export Table', layout=widgets.Layout(width='10%')) def export_results_table(button): try: if button.value == 'Export Table': root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() export_results_table_filepath.value = str(filedialog.asksaveasfilename(defaultextension='.csv', title='Save CSV Report')) root.destroy() except Exception as e: print(e) export_results_table_browse_button.disabled=True export_results_table_browse_button.description='Use Text Field' out_path = export_results_table_filepath.value sprit_hvsr.get_report(hvsr_results, report_format='csv', export_path=out_path, csv_overwrite_opt='overwrite') export_results_table_browse_button.on_click(export_results_table) export_results_table_read_button.on_click(export_results_table) results_table_export_hbox = widgets.HBox([export_results_table_filepath, export_results_table_read_button, export_results_table_browse_button]) results_table_vbox = widgets.VBox([results_table, results_table_export_hbox]) global results_tab results_subtabs = widgets.Tab([results_graph_widget, printed_results_textArea, results_table_vbox]) results_tab = widgets.VBox(children=[results_subtabs]) results_subtabs.set_title(0, "Plot") results_subtabs.set_title(1, "Peak Tests") results_subtabs.set_title(2, "Peak Table") widget_param_dict = { 'fetch_data': {'source': data_source_type, 'trim_dir': trim_directory, 'export_format': trim_export_dropdown, 'detrend': detrend_type_dropdown, 'detrend_options': detrend_options, 'verbose': verbose_check}, 'remove_noise': { 'sat_percent': max_saturation_pct, 'noise_percent': max_window_pct, 'sta': sta, 'lta': lta, 'stalta_thresh': [stalta_thresh_low, stalta_thresh_hi], 'warmup_time': warmup_time, 'cooldown_time': cooldown_time, 'min_win_size': noisy_window_length, 'remove_raw_noise': raw_data_remove_check, 'verbose': verbose_check}, 'generate_psds': {'verbose': verbose_check, 'skip_on_gaps':skip_on_gaps, 'db_bins':[db_bins_min, db_bins_max, db_bins_step], 'ppsd_length':ppsd_length, 'overlap':overlap_pct, 'special_handling':special_handling_dropdown, 'period_smoothing_width_octaves':period_smoothing_width, 'period_step_octaves':period_step_octave, 'period_limits':[hvsr_band_min_box, hvsr_band_max_box]}, 'process_hvsr': {'method': h_combine_meth, 'smooth': smooth_hv_curve, 'freq_smooth': freq_smoothing, 'f_smooth_width': freq_smooth_width, 'resample': resample_hv_curve, 'verbose': verbose_check}, 'remove_outlier_curves': {'rmse_thresh': rmse_thresh, 'use_percentile': rmse_pctile_check, 'use_hv_curve': use_hv_curve_rmse, 'verbose': verbose_check}, 'check_peaks': {'hvsr_band': [hvsr_band_min_box, hvsr_band_max_box], 'peak_freq_range': [peak_freq_range_min_box, peak_freq_range_max_box], 'verbose': verbose_check}, 'get_report': { 'export_path': export_results_table_filepath, 'verbose': verbose_check}} # SPRIT WIDGET # Add all a tab and add the grid to it global sprit_tabs sprit_tabs = widgets.Tab([input_tab, preview_tab, settings_tab, log_tab, results_tab]) sprit_tabs.set_title(0, "Input") sprit_tabs.set_title(1, "Preview") sprit_tabs.set_title(2, "Settings") sprit_tabs.set_title(3, "Log") sprit_tabs.set_title(4, "Results") sprit_title = widgets.Label(value='SPRIT', layout=widgets.Layout(width='150px')) sprit_subtitle = widgets.Label(value='Tools for ambient siesmic noise analysis using HVSR', layout=widgets.Layout(flex='1', justify_content='flex-start', align_content='flex-end')) # Function to open a link def open_dist(button): link = 'https://pypi.org/project/sprit/' webbrowser.open_new_tab(link) def open_repo(button): link = 'https://github.com/RJbalikian/SPRIT-HVSR' webbrowser.open_new_tab(link) def open_docs(button): link = 'https://rjbalikian.github.io/SPRIT-HVSR/main.html' webbrowser.open_new_tab(link) sourcebutton = widgets.Button(description="PyPI", layout=widgets.Layout(width='4%', justify_content='flex-end',align_content='flex-end')) repobutton = widgets.Button(description="Repo", layout=widgets.Layout(width='4%', justify_content='flex-end',align_content='flex-end')) docsbutton = widgets.Button(description="Docs", layout=widgets.Layout(width='8%', justify_content='flex-end',align_content='flex-end')) # Attach the open_link function to the button's on_click event sourcebutton.on_click(open_dist) repobutton.on_click(open_repo) docsbutton.on_click(open_docs) titlehbox = widgets.HBox([sprit_title, sprit_subtitle, repobutton, sourcebutton, docsbutton], layout = widgets.Layout(align_content='space-between')) title_style = { 'font_family': 'Arial, sans-serif', 'font_size': '36px', 'font_weight': 'bold', 'color': 'black' } # Apply the style to the label sprit_title.style = title_style sprit_widget = widgets.VBox([titlehbox, sprit_tabs]) def observe_children(widget, callback): if hasattr(widget, 'children'): for child in widget.children: child.observe(callback) observe_children(child, callback) def any_update(change): update_input_param_call() update_fetch_data_call() update_remove_noise_call() update_generate_ppsd_call() update_process_hvsr_call() update_remove_outlier_curve_call() update_check_peaks_call() update_plot_string() observe_children(sprit_tabs, any_update) # Display the tab display(sprit_widget)