Module sprit.sprit_jupyter_UI
Functions to create jupyter notebook widget UI
Functions
def create_jupyter_ui()-
Expand source code
def create_jupyter_ui(): """Function that generates the user interface for Jupyter Notebooks. This interface uses ipywidgets, plotly, and IPython to create a user interface for processing data in a Jupyter notebook. This is functionally equivalent to sprit.gui('nb'). SEE ALSO -------- gui """ global hvsr_data global results_fig global log_textArea ui_width = 20 ui_height= 12 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() # Input Params Accordion input_params_grid = widgets.GridspecLayout(5, 10) fetch_data_grid = widgets.GridspecLayout(7, 10) calculate_azimuths_grid = widgets.GridspecLayout(5, 10) noise_removal_grid = widgets.GridspecLayout(10, 10) generate_psds_grid = widgets.GridspecLayout(6, 5) process_hvsr_grid = widgets.GridspecLayout(5, 10) remove_outliers_grid = widgets.GridspecLayout(5, 10) # A text box for the site name site_textbox = widgets.Text(description='Site Name', value='HVSR_Site', placeholder='HVSR_Site') # Text box for project/county name project_textbox = widgets.Text(description='Project', placeholder= "Project or County Name") # A text box labeled Metadata Filepath metadata_filepath = widgets.Text(description='Metadata', placeholder='Filepath to file to be read by obspy.read_inventory()', layout=widgets.Layout(width='auto')) # A button next to it labeled "Browse" browse_metadata_button = widgets.Button(description='Browse', layout=widgets.Layout(width='auto')) def select_metapath(event): try: from tkinter import tk, filedialog 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) # Dropdown with instrument types instrument_dropdown = widgets.Dropdown(options=[('Raspberry Shake', 'raspberry shake'), ('Tromino Yellow', 'tromino yellow'), ('Tromino Blue', 'tromino blue'), ('Other Seismometer', 'seismometer')], #style={'description_width': 'initial'}, description='Instrument:', layout=widgets.Layout(width='100%')) 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(description='Inst. Settings', placeholder='Filepath to data with instrument settings', layout=widgets.Layout(width='auto')) instrument_read_button = widgets.Button(description='Browse', icon='fa-file-import', layout=widgets.Layout(width='auto')) def select_inst(event): try: if event.description == 'Select .inst file': from tkinter import tk, filedialog 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 'metadata' in inst_settings.keys(): metadata_filepath.value = inst_settings['metadata'] if 'hvsr_band' in inst_settings.keys(): hvsr_band_rangeSlide.value = (inst_settings['hvsr_band'][0], inst_settings['hvsr_band'][1]) except Exception as e: print(e) instrument_read_button.disabled = True instrument_read_button.description = 'Use Text Field' instrument_read_button.on_click(select_inst) # Input parameters parameters input_params_grid[0, 0:2] = network_textbox input_params_grid[0, 6:8] = location_textbox input_params_grid[1, 0:2] = z_channel_textbox input_params_grid[1, 2:4] = e_channel_textbox input_params_grid[1, 4:6] = n_channel_textbox input_params_grid[2, :9] = metadata_filepath input_params_grid[2, 9:] = browse_metadata_button input_params_grid[3, :9] = inst_settings_text input_params_grid[3, 9:] = instrument_read_button # Acquisition Accordion instrument_grid = widgets.GridspecLayout(5, 10) # Date Picker labelled "Acquisition Date" acquisition_date_picker = widgets.DatePicker(description='Acq. Date:', placeholder=sprit_hvsr.NOWTIME.date(), value=sprit_hvsr.NOWTIME.date()) # Label that shows the Date currently selected in the Date Picker acquisition_doy = widgets.IntText(description='Day of Year', 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', value='23:59',) #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(description='Time Zone:', options=tzlist, value=_get_default(sprit_hvsr.input_params, 'tzone')) 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'), layout=widgets.Layout(width='100%'), placeholder=_get_default(sprit_hvsr.input_params, 'xcoord')) #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'), layout=widgets.Layout(width='100%'), placeholder=_get_default(sprit_hvsr.input_params, 'ycoord')) #location_grid[1, 0] = ycoord_textbox # Z coordinate input zcoord_textbox = widgets.FloatText(description='Z Coordinate', tooltip='elevation:', layout=widgets.Layout(width='100%'), value=_get_default(sprit_hvsr.input_params, 'elevation'), placeholder=_get_default(sprit_hvsr.input_params, 'elevation')) #location_grid[2, 0] = zcoord_textbox # Input CRS input input_crs_textbox = widgets.Text(description='Input CRS:', layout=widgets.Layout(width='75%'), 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='75%'), 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 # Z coordinate unit input elev_unit_dropdown = widgets.Dropdown(options=[('Feet', 'feet'), ('Meters', 'meters')], layout=widgets.Layout(width='75%'), value=_get_default(sprit_hvsr.input_params, 'elev_unit'), description='Z Unit:', tooltip='elev_unit') #location_grid[2, 1] = elev_unit_dropdown # Data format (for obspy format to use to read in) peak_freq_rangeSlide = widgets.FloatRangeSlider(value=sprit_hvsr.DEFAULT_BAND, min=0.1, max=64, step=0.1, description='Peak Range', tooltip='Define the frequency range over which to search for peaks', readout_format='.1f', layout=widgets.Layout(height='auto', width='auto'), ) hvsr_band_rangeSlide = widgets.FloatRangeSlider(value=sprit_hvsr.DEFAULT_BAND, min=0.1, max=64, step=0.1, description='HVSR Band', tooltip='Define the frequency range over which HVSR data is processed', readout_format='.1f', layout=widgets.Layout(height='auto', width='auto'), ) # FETCH DATA ACCORDION # 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.Text(description='Options', tooltip='detrend_options', placeholder="order="+str(_get_default(sprit_hvsr.fetch_data, 'detrend_options')), value="order="+str(_get_default(sprit_hvsr.fetch_data, 'detrend_options')), layout=widgets.Layout(width='auto')) filter_type_dropdown = widgets.Dropdown(options=[('Bandpass', 'bandpass'), ('Bandstop', 'bandstop'), ('Highpass', 'highpass'), ('Lowpass', 'lowpass'), ('Lowpass (Cheby 2)', 'lowpass_cheby_2'), ('Lowpass (FIR)', 'lowpass_fir'), ('Remez (FIR)', 'remez_fir'), ('None', 'none')], value="none", description='Filter type', layout=widgets.Layout(width='auto')) filter_options = widgets.Text(description='Options', tooltip="Options for obspy.filter() method in a format: 'option_name=option_value, 2ndoptname=2ndoptvalue'", placeholder=str(_get_default(sprit_hvsr.fetch_data, 'filter_options')), value=str(_get_default(sprit_hvsr.fetch_data, 'filter_options')), layout=widgets.Layout(width='auto')) # A text to specify the trim directory data_export_path_textbox = widgets.Text(description='Export Path', value="None",#pathlib.Path().home().as_posix(), layout=widgets.Layout(width='auto')) data_export_format_dropdown = widgets.Dropdown(options=OBSPY_FORMATS, value='MSEED', description='Format', layout=widgets.Layout(width='auto')) update_metadata_checkbox = widgets.Checkbox(value=True, description='Update Metadata', disabled=False, indent=False, tooltip='Only applicable if metadata specified') # 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': from tkinter import tk, filedialog 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) fetch_data_grid[0, :] = proc_settings_hbox fetch_data_grid[1, 0] = data_export_format_dropdown fetch_data_grid[2, 0] = detrend_type_dropdown fetch_data_grid[2, 1] = detrend_options fetch_data_grid[3, 0] = filter_type_dropdown fetch_data_grid[3, 1] = filter_options fetch_data_grid[4, :] = update_metadata_checkbox fetch_data_grid[5, 0] = widgets.Label('Data Export') fetch_data_grid[5, 1:6] = data_export_path_textbox fetch_data_grid[5, 6:8] = data_export_format_dropdown # Calculate Azimuth #azimuth_angle=45, azimuth_type='multiple', azimuth_unit='degrees', verbose=False azimuth_angle_slide = widgets.IntSlider(value=45, min=0, max=360, step=1, description='Angle', disabled=False, continuous_update=False, orientation='horizontal', readout=True) azimuth_type_dropdown = widgets.Dropdown(options=[('Multiple/steps', 'multiple'), ('Single', 'single'), ("None", None)], value=None, description='Type') azimuth_unit_dropdown = widgets.Dropdown(options=[('°', 'degrees'), ('rad', 'radians')], value='degrees', description='Unit') calculate_azimuths_grid[0, 0] = widgets.Label("Azimuth information") calculate_azimuths_grid[1, 0] = azimuth_type_dropdown calculate_azimuths_grid[2, 0] = azimuth_unit_dropdown calculate_azimuths_grid[3, :] = azimuth_angle_slide # Noise removal # remove_method=None, # processing_window=None, # sat_percent=0.995, # noise_percent=0.8, # sta=2, lta=30, stalta_thresh=[8, 16], # std_ratio_thresh=2.0, std_window_size=20.0, min_std_win=5.0, # warmup_time=0, cooldown_time=0, min_win_size=1, # remove_raw_noise=False, remove_method_select = widgets.SelectMultiple(options=[('None', None), ("Moving St. Dev.", "moving_std"), ('Saturation Threshold', 'saturation'), ("Noise Threshold","noise"), ('STA/LTA', 'stalta'), ('Warmup', "warmup"), ("Cooldown", "cooldown"), ("Processing Windows", 'processing_window')], value=[None], rows=8, description='Method', disabled=False ) std_ratio_thresh_float = widgets.BoundedFloatText(value=float(_get_default(sprit_hvsr.remove_noise, "std_ratio_thresh")), min=0.0, max=50, step=0.25, description='StDev Ratio', tooltip='The threshold for the ratio between the moving standard deviation/total standard deviation of the record to use as a threshold', disabled=True) std_window_size_float = widgets.BoundedFloatText(value=float(_get_default(sprit_hvsr.remove_noise, "std_window_size")), min=0.0, max=60, step=0.5, description='StDev Window Size', tooltip='The size of the moving standard deviation window, in seconds', disabled=True) min_std_win = widgets.BoundedFloatText(value=float(_get_default(sprit_hvsr.remove_noise, "min_std_win")), min=0.0, max=30, step=0.25, description='Min. StDev Window Size', tooltip='The minimum size of the window that can be removed by the moving standard deviation method, in seconds', disabled=True) sat_percent_float = widgets.BoundedFloatText(value=float(_get_default(sprit_hvsr.remove_noise, "sat_percent")), min=0.0, max=1.0, step=0.05, description='Saturation %', tooltip='Percent (0-1) of absolute value of maximum value in dataset, above which value data is excluded from analysis', disabled=True) noise_percent_float = widgets.BoundedFloatText(value=float(_get_default(sprit_hvsr.remove_noise, "noise_percent")), min=0.0, max=1.0, step=0.05, description='Noise %', tooltip='Percent (0-1) of absolute value of maximum value in dataset, above which value data is excluded from analysis if persistent for min_win_size', disabled=True) sta_float = widgets.FloatText(value=float(_get_default(sprit_hvsr.remove_noise, "sta")), step=0.1, description='STA', tooltip='Length of window to use for short term average', disabled=True) lta_float = widgets.FloatText(value=float(_get_default(sprit_hvsr.remove_noise, "lta")), step=0.1, description='LTA', tooltip='Length of window to use for long term average', disabled=True) stalta_floatSlide = widgets.FloatRangeSlider( value=_get_default(sprit_hvsr.remove_noise, "stalta_thresh"), min=0, max=100, step=0.1, description='STALTA Thresh.', disabled=True, continuous_update=False, orientation='horizontal', readout=True, tooltip='The threshold at which an event is triggered, and at which the event is no longer considered active', readout_format='.1f') warmup_time_int = widgets.IntText( value=int(_get_default(sprit_hvsr.remove_noise, "warmup_time")), description='Warmup [s]', tooltip= 'Warmup time in seconds (time to exclude from start of record)', disabled=True ) cooldown_time_int = widgets.IntText( value=int(_get_default(sprit_hvsr.remove_noise, "cooldown_time")), description='Cooldown [s]', tooltip= 'Cooldown time in seconds (time to exclude from end of record)', disabled=True ) min_win_size_float = widgets.FloatText(value=float(_get_default(sprit_hvsr.remove_noise, "min_win_size")), description='Min Window Size', tooltip='Minimum length (in seconds) of windows that can be removed', disabled=True) proc_wind_text = widgets.Text(value='None', tooltip='Manual specification of windows in the format: [[Starttime0, EndTime0], [Starttime1, Endtime1],....]', description='Windows', disabled=True) raw_noise_checkbox = widgets.Checkbox(value=False, description='Use raw stream', disabled=True, indent=False) def on_remove_method_change(event): print('disabling') stalta_disabled = True mst_disabled = True sat_disabled = True noise_disabled = True warm_disabled = True cool_disabled = True proc_win_disabled = True any_method_disabled = True if 'stalta' in remove_method_select.value: stalta_disabled = False any_method_disabled = False if 'moving_std' in remove_method_select.value: mst_disabled = False any_method_disabled = False if 'saturation' in remove_method_select.value: sat_disabled = False any_method_disabled = False if 'noise' in remove_method_select.value: noise_disabled = False any_method_disabled = False if 'warmup' in remove_method_select.value: warm_disabled = False any_method_disabled = False if 'cooldown' in remove_method_select.value: cool_disabled = False any_method_disabled = False if 'processing_window' in remove_method_select.value: proc_win_disabled = False any_method_disabled = False # Now disable them all...or not min_std_win.disabled = std_window_size_float.disabled = std_ratio_thresh_float.disabled = mst_disabled sat_percent_float.disabled = sat_disabled noise_percent_float.disabled = noise_disabled sta_float.disabled = lta_float.disabled = stalta_floatSlide.disabled = stalta_disabled warmup_time_int.disabled = warm_disabled cooldown_time_int.disabled = cool_disabled min_win_size_float.disabled = any_method_disabled proc_wind_text.disabled = proc_win_disabled raw_noise_checkbox.disabled = any_method_disabled remove_method_select.observe(on_remove_method_change) # Set up arrangement noise_removal_grid[0:5, :2] = remove_method_select noise_removal_grid[0:5, 2:4] = raw_noise_checkbox noise_removal_grid[5, :1] = widgets.Label("St. Dev. Ratio (Total / Moving)") noise_removal_grid[5, 2:4] = std_ratio_thresh_float noise_removal_grid[5, 4:6] = std_window_size_float noise_removal_grid[5, 6:8] = min_std_win noise_removal_grid[6, :2] = sat_percent_float noise_removal_grid[6, 2:4] = noise_percent_float noise_removal_grid[7, 0:2] = sta_float noise_removal_grid[7, 2:4] = lta_float noise_removal_grid[7, 4:6] = stalta_floatSlide noise_removal_grid[8, 0:2] = warmup_time_int noise_removal_grid[8, 2:4] = cooldown_time_int noise_removal_grid[9, :] = proc_wind_text # Generate PSDs # window_length=30.0, # overlap_pct=0.5, # window_type='hann', window_length_method='length', # remove_response=False, skip_on_gaps=True, # num_freq_bins=512, # obspy_ppsds=False, azimuthal_psds=False, verbose=False window_length_float = widgets.FloatText(value=float(_get_default(sprit_hvsr.generate_psds, "window_length")), description='Length', tooltip='Length of windows used for FFT analysis, in seconds or number (depending on window_length_method)', disabled=False) window_length_method_dropdown = widgets.Dropdown(options=[('Length', 'length'), ('Number of windows', 'number')], value='length', tooltip="How to define the window length (by length or by number of windows)", description='Method',) overlap_pct_float = widgets.BoundedFloatText(value=float(_get_default(sprit_hvsr.generate_psds, "overlap_pct")), min=0, max=1.0, step=0.01, description='Overlap %', tooltip='Percentage by which to overlap windows used for FFT analysis', disabled=False) window_type_dropdown = widgets.Dropdown(options=[('Hann', 'hann'), ("Boxcar", 'boxcar'), ('Triangle', 'triang'), ('Blackman', 'blackman'), ('Hamming', 'hamming'), ('Bartlett', 'bartlett'), ('Flattop', 'flattop'), ('Parzen', 'parzen'), ('Bohman', 'bohman'), ('Blackman-Harris', 'blackmanharris'), ('Nuttal', 'nuttall'), ('Barthan', 'barthann'), ('Cosine', 'cosine'), ('Exponential', 'exponential'), ('Tukey', 'tukey'), ('Taylor', 'taylor'), ('Lanczos', 'lanczos')], value='hann', tooltip='Type of window to use. See scip.signal.get_window() for more information.', description='Window Type',) remove_response_check = widgets.Checkbox(value=False, description='Remove Response', tooltip='Whether to remove instrument response. Must have metadata attached to data.', disabled=False) skip_on_gaps_check = widgets.Checkbox(value=False, description='Skip on Gaps', tooltip='Whether to skip windows if there are gaps', disabled=False) obspy_ppsds_check = widgets.Checkbox(value=False, description='Use Obspy PPSDs', tooltip='Whether to use the Obspy PPSD class to create PPSDs', disabled=False) azimuthal_psds_check = widgets.Checkbox(value=False, description='Use Azimuths', tooltip='Whether to generate PSDs based on azimuths', disabled=False) num_freq_bins_dropdown = widgets.Dropdown(options=[64,128,512,1024,2048], value=512, tooltip='The number of frequency bins to use in creating PSDs', description='# Freq. Bins',) hvsr_band_gpsd_Rangeslide = widgets.FloatRangeSlider(value=sprit_hvsr.DEFAULT_BAND, min=0.1, max=64, step=0.1, description='HVSR Band', tooltip='Define the frequency range over which HVSR data is processed', readout_format='.1f', layout=widgets.Layout(height='auto', width='auto')) widgets.link((hvsr_band_gpsd_Rangeslide, 'value'), (hvsr_band_rangeSlide, 'value')) peak_freq_gpsd_rangeSlide = widgets.FloatRangeSlider(value=sprit_hvsr.DEFAULT_BAND, min=0.1, max=64, step=0.1, description='Peak Range', tooltip='Define the frequency range over which to search for peaks', readout_format='.1f', layout=widgets.Layout(height='auto', width='auto')) widgets.link((peak_freq_gpsd_rangeSlide, 'value'), (peak_freq_rangeSlide, 'value')) # Obspy PPSD SETTINGS 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_rangeSlide.value[1]), 3) maxPLim = round(1/(hvsr_band_rangeSlide.value[0]), 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) generate_psds_grid[0, 0] = widgets.Label("Window settings") generate_psds_grid[0, 1] = window_length_float generate_psds_grid[0, 2] = window_length_method_dropdown generate_psds_grid[1, 1] = overlap_pct_float generate_psds_grid[1, 2] = window_type_dropdown generate_psds_grid[2, 0] = remove_response_check generate_psds_grid[2, 1] = skip_on_gaps_check generate_psds_grid[2, 2] = obspy_ppsds_check generate_psds_grid[2, 3] = azimuthal_psds_check generate_psds_grid[3, 0] = num_freq_bins_dropdown generate_psds_grid[4, 0:2] = peak_freq_gpsd_rangeSlide generate_psds_grid[5, 0:2] = hvsr_band_gpsd_Rangeslide # Process HVSR # horizontal_method=None, # smooth=True, freq_smooth='konno ohmachi', f_smooth_width=40, # resample=True, # outlier_curve_rmse_percentile=False, # azimuth=None, # verbose=False # HVSR SETTINGS SUBTAB h_combine_meth_dropdown = widgets.Dropdown(description='', value=3, tooltip="Select how to combine the horizontal components", options=[('1. Differential Field Assumption', 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), ('7. Minimum Horizontal Value | H = max(N, E)', 7), ('8. Single Azimuth | H = H2·cos(az) + H1·sin(az)', 8)]) freq_smoothing_dropdown = widgets.Dropdown(description='', value='konno ohmachi', tooltip="Select which type of frequency smoothing algorithm to use", options=[('Konno-Ohmachi', 'konno ohmachi'), ('Constant','constant'), ('Proportional', 'proportional'), ('None', None)]) freq_smooth_width_float = widgets.FloatText(description='Width', tooltip="Specify the width for the smoothing algorithm", placeholder=40, value=40) resample_hv_curve_bool = widgets.Checkbox(value=True, description='Resample', tooltip="Whether to resample the data to a speicified number of frequency bins.") resample_hv_curve = widgets.IntText(description='', tooltip="If resampling, how many frequency points/bins to use.", placeholder=512, value=512) smooth_hv_curve_bool = widgets.Checkbox(value=True,description='Smooth', tooltip='Whether to smooth the data (this does not account for logarithmic frequency width increases.)') smooth_hv_curve = widgets.IntText(description='', tooltip="The window width to use for smoothing.", placeholder=51, value=51) peak_selection_type = widgets.Dropdown(description='Peak 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_grid[0, 0] = widgets.Label("Horizontal Combination Method") process_hvsr_grid[0, 1:] = h_combine_meth_dropdown process_hvsr_grid[1, 0] = widgets.Label("Frequency Smoothing Operation") process_hvsr_grid[1, 1] = freq_smoothing_dropdown process_hvsr_grid[1, 2] = freq_smooth_width_float process_hvsr_grid[2, 0] = resample_hv_curve_bool process_hvsr_grid[2, 1] = resample_hv_curve process_hvsr_grid[3, 0] = smooth_hv_curve_bool process_hvsr_grid[3, 1] = smooth_hv_curve process_hvsr_grid[4, 0] = peak_selection_type # Remove outlier curves # outlier_method='prototype', # use_percentile=True, # use_hv_curve=False, # outiler_threshold=98, # min_pts=5, # plot_engine='matplotlib', show_outlier_plot=False, generate_outlier_plot=True, # verbose=False outlier_method_dropdown = widgets.Dropdown(description='Method', value=None, tooltip="Select which type of outlier removal algorithm to use.", options=[('Prototype/RMSE', 'prototype'), ('DBSCAN','dbscan'), ('None', None)]) outlier_pctile_check = widgets.Checkbox(description='Use percentile', value=True) use_hv_curve_outliers_check = widgets.Checkbox(description="Use HV Curves", tooltip='Whether to use HV Curve Outliers or PSD curves. HV Curves are only 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=False) outlier_threshold_slider = widgets.FloatSlider(value=_get_default(sprit_hvsr.remove_outlier_curves, 'outlier_threshold'), min=0, max=100, step=0.1, description='Threshold', layout=widgets.Layout(height='auto', width='auto'), disabled=False) min_pts_float = widgets.FloatText(description='Min. Pts.', tooltip="The minimum number of points in a neighborhood, when 'DBSCAN' is used for the outlier method.", placeholder=5, value=5, disabled=True) def outlier_method_update(event): if 'dbscan' in str(outlier_method_dropdown.value).lower(): min_pts_float.disabled=False else: min_pts_float.disabled=True outlier_method_dropdown.observe(outlier_method_update) # Define Outlier Fig global outlier_fig outlier_fig = go.FigureWidget() outlier_graph_widget = widgets.Output() remove_outliers_grid[0, 0] = widgets.Label("Outlier Curve Removal") remove_outliers_grid[1, 0] = use_hv_curve_outliers_check remove_outliers_grid[1, 1] = outlier_method_dropdown remove_outliers_grid[1, 2] = min_pts_float remove_outliers_grid[2, 0] = outlier_pctile_check remove_outliers_grid[2, 1:] = outlier_threshold_slider # PYTHON API ACCORDION inputAPI_grid = widgets.GridspecLayout(6, 10) # A text label with "input_params()" #run_prefix = widgets.HTML(value='<style>p {word-wrap: break-word}</style> <p>' + 'sprit.run' + '</p>', # layout=widgets.Layout(width='fill', justify_content='flex-end',align_content='flex-start')) #run_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] = run_prefix #inputAPI_grid[0, 1:] = run_call # 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 # Generate PPSDs python call generate_psds_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_psds_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[2, 0] = generate_psds_prefix inputAPI_grid[2, 1:] = generate_psds_call # Process HVSR call 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='()') inputAPI_grid[3, 0] = process_hvsr_call_prefix inputAPI_grid[3, 1:] = process_hvsr_call # Remove Outlier Curves call remove_outlier_curves_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_curves_call = widgets.HTML(value='()') inputAPI_grid[4, 0] = remove_outlier_curves_prefix inputAPI_grid[4, 1:] = remove_outlier_curves_call # Check peaks 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]) inputAPI_grid[5, 0] = check_peaks_call_prefix inputAPI_grid[5, 1:] = check_peaks_call # Set it all in place #metaLabel = widgets.Label('Input Params', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #fetchLabel = widgets.Label('Fetch Data', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #remNoiseLabel = widgets.Label('Noise Removal', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #azimuthLabel = widgets.Label('Calculate Azimuths', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #genPSDLabel = widgets.Label('Generate PSDs', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #procHVSRLabel = widgets.Label('Process HVSR', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #remCurveLabel = widgets.Label('Remove Outlier Curves', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #checkPeakLabel = widgets.Label('Check Peaks', layout=widgets.Layout(height='20%', align_content='center', justify_content='flex-end')) #reportLabel = widgets.Label('Get Reports', 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 = [input_params_grid, fetch_data_grid, calculate_azimuths_grid, noise_removal_grid, generate_psds_grid, process_hvsr_grid, remove_outliers_grid, inputAPI_grid] input_accordion.titles = ["Input Params", "Fetch Data", "Calculate Azimuths", "Noise Removal", "Generate PSDs", "Process HVSR", "Remove Outlier Curves", "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 tenpct_spacer = widgets.Button(description='', layout=widgets.Layout(width='20%', visibility='hidden')) fivepct_spacer = widgets.Button(description='', layout=widgets.Layout(width='5%', visibility='hidden')) # 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='100%')) # A button next to input_data text labeled "Browse" browse_data_button = widgets.Button(description='Browse', layout=widgets.Layout(width='100%')) def select_datapath(event): try: from tkinter import tk, filedialog root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() if data_source_type.value == 'file' or data_source_type.value == 'batch': filepaths = filedialog.askopenfilenames(defaultextension='.MSEED', title='Select Data File') if isinstance(filepaths, tuple): if len(filepaths) == 1: filepaths = str(filepaths[0]) data_filepath.value = str(filepaths) 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) def on_input_data_change(event): export_directory_text.value = pathlib.Path(data_filepath.value).parent.as_posix() if export_directory_text.value == '.' or not pathlib.Path(export_directory_text.value).exists(): export_directory_text.value = pathlib.Path().home().as_posix() data_filepath.observe(on_input_data_change) # 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='90%')) 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) # 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='8%', 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='5%', justify_content='flex-end')) # 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='100%')) # A dark yellow button labeled "Read Data" read_data_button = widgets.Button(description='Read Data', button_style='warning') # A forest green button labeled "Run" process_hvsr_button = widgets.Button(description='Run', button_style='success') # Update input_param call def update_input_param_call(): input_param_text = f"""(input_data='{data_filepath.value}', metadata='{metadata_filepath.value}', site='{site_textbox.value}', project='{project_textbox.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='{elev_unit_dropdown.value}', instrument='{instrument_dropdown.value}', hvsr_band={hvsr_band_rangeSlide.value}, peak_freq_range={[peak_freq_rangeSlide.value[0], peak_freq_rangeSlide.value[1]]}, 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}, data_export_path={data_export_path_textbox.value}, data_export_format={data_export_format_dropdown.value}, detrend_type={detrend_type_dropdown.value}, detrend_options={detrend_options.value}, filter_type={filter_type_dropdown.value}, filter_options={filter_options.value}, update_metadata={update_metadata_checkbox.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() main_settings_grid = widgets.GridspecLayout(15, 10) main_settings_grid[0, 0:6] = data_filepath main_settings_grid[0, 6:7] = browse_data_button main_settings_grid[0, 8:] = data_source_type main_settings_grid[1,:] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) main_settings_grid[2, 0:2] = site_textbox main_settings_grid[2, 2:4] = project_textbox main_settings_grid[3, 0:2] = station_textbox main_settings_grid[3, 2:4] = instrument_dropdown main_settings_grid[4,:6] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) main_settings_grid[5, 0:1] = xcoord_textbox main_settings_grid[5, 2:3] = ycoord_textbox main_settings_grid[5, 4:5] = zcoord_textbox main_settings_grid[6, 0] = input_crs_textbox main_settings_grid[6, 2] = output_crs_textbox main_settings_grid[6, 4] = elev_unit_dropdown main_settings_grid[7,:6] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) main_settings_grid[8, 0:2] = acquisition_date_picker main_settings_grid[8, 2] = acquisition_doy main_settings_grid[9,0:2] = start_time_picker main_settings_grid[9,2] = end_time_picker main_settings_grid[9,3:5] = time_zone_dropdown main_settings_grid[10,:6] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) main_settings_grid[11,0:4] = peak_freq_rangeSlide main_settings_grid[12,0:4] = hvsr_band_rangeSlide main_settings_grid[13,:] = widgets.HTML('<hr>', layout=widgets.Layout(height='auto', width='auto', justify_content='center', align_items='center')) input_accordion_box.children = [input_accordion] #main_settings_grid[6:9, :] = input_accordion_box main_settings_grid[14, 0:8] = progress_bar main_settings_grid[14, 8] = read_data_button main_settings_grid[14, 9] = process_hvsr_button # Create a GridBox with 12 rows and 20 columns global input_tab input_tab = widgets.GridBox(layout=widgets.Layout(grid_template_columns='repeat(10, 1)', grid_template_rows='repeat(12, 1)')) input_subtabs = widgets.Tab([main_settings_grid, input_accordion_box]) input_subtabs.set_title(0, "Main Inputs") input_subtabs.set_title(1, "Additional Settings") input_tab = widgets.VBox(children=[input_subtabs]) def get_input_params(): input_params_kwargs={ 'input_data':data_filepath.value, 'project':project_textbox.value, 'metadata':metadata_filepath.value, 'site':site_textbox.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':elev_unit_dropdown.value,'depth':0, 'input_crs':input_crs_textbox.value,'output_crs':output_crs_textbox.value, 'hvsr_band':hvsr_band_rangeSlide.value, 'peak_freq_range':peak_freq_rangeSlide.value} return input_params_kwargs def get_fetch_data_params(): fetch_data_kwargs = { 'source':data_source_type.value, 'data_export_path':data_export_path_textbox.value, 'export_format':data_export_format_dropdown.value, 'detrend_type':detrend_type_dropdown.value, 'detrend_options':detrend_options.value, 'filter_type':filter_type_dropdown.value, 'filter_options':filter_options.value, 'update_metadata':update_metadata_checkbox.value } if str(fetch_data_kwargs['detrend_type']).lower() == 'none': fetch_data_kwargs['detrend_type'] = None if str(fetch_data_kwargs['data_export_path']).lower() == 'none': fetch_data_kwargs['data_export_path'] = None if str(fetch_data_kwargs['filter_type']).lower() == 'none': fetch_data_kwargs['filter_type'] = 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() log_textArea.value += f"\n\n{datetime.datetime.now()}\ninput_params():\n'{ip_kwargs}" hvsr_data = sprit_hvsr.input_params(**ip_kwargs, verbose=verbose_check.value) if button.description == 'Read Data': progress_bar.value = 0.333 else: progress_bar.value = 0.1 fd_kwargs = get_fetch_data_params() log_textArea.value += f"\n\n{datetime.datetime.now()}\fetch_data():\n'{fd_kwargs}" log_textArea.value += '\n'.join([str((k, v)) for k, v in hvsr_data.items()]) hvsr_data = sprit_hvsr.fetch_data(hvsr_data, **fd_kwargs, verbose=verbose_check.value) if button.description == 'Read Data': progress_bar.value = 0.666 else: progress_bar.value = 0.2 use_hv_curve_outliers_check.value = False use_hv_curve_outliers_check.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 = { 'window_length':window_length_float.value, 'overlap_pct':overlap_pct_float.value, 'window_type':window_type_dropdown.value, 'window_length_method':window_length_method_dropdown.value, 'remove_response':remove_response_check.value, 'skip_on_gaps':skip_on_gaps_check.value, 'num_freq_bins':num_freq_bins_dropdown.value, 'obspy_ppsds':obspy_ppsds_check.value, 'azimuthal_psds':azimuthal_psds_check.value, 'verbose':verbose_check.value, 'obspy_ppsds_kwargs':{'db_bins':[db_bins_min.value, db_bins_max.value, db_bins_step.value], 'ppsd_length':ppsd_length.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]} } if str(ppsd_kwargs['obspy_ppsds_kwargs']['special_handling']).lower() == 'none': ppsd_kwargs['obspy_ppsds_kwargs']['special_handling'] = None return ppsd_kwargs # Update process_hvsr call def update_generate_psds_call(): #gp_kwargs = get_generate_ppsd_kwargs() gp_text = f"""(hvsr_data=hvsr_data, window_length={window_length_float.value}, overlap_pct={overlap_pct_float.value}, window_type={window_type_dropdown.value}, window_length_method={window_length_method_dropdown.value}, remove_response={remove_response_check.value}, skip_on_gaps={skip_on_gaps_check.value}, num_freq_bins={num_freq_bins_dropdown.value}, obspy_ppsds={obspy_ppsds_check.value}, azimuthal_psds={azimuthal_psds_check.value}, ... obspy_ppsd_kwargs=..., verbose={verbose_check.value})""" generate_psds_call.value='<style>p {word-wrap: break-word}</style> <p>' + gp_text + '</p>' update_generate_psds_call() def get_remove_outlier_curve_kwargs(): roc_kwargs = { 'outlier_method':outlier_method_dropdown.value, 'use_percentile':outlier_pctile_check.value, 'use_hv_curves':use_hv_curve_outliers_check.value, 'outlier_threshold':outlier_threshold_slider.value, 'min_pts':min_pts_float.value, '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={'horizontal_method':h_combine_meth_dropdown.value, 'smooth':smooth_value, 'freq_smooth':freq_smoothing_dropdown.value, 'f_smooth_width':freq_smooth_width_float.value, 'resample':resample_value, 'verbose':verbose_check.value} return ph_kwargs # Update process_hvsr call def update_process_hvsr_call(): #ph_kwargs = get_process_hvsr_kwargs() ph_text = f"""(hvsr_data=hvsr_data, horizontal_method={h_combine_meth_dropdown.value}, smooth={smooth_hv_curve_bool.value}, freq_smooth={freq_smoothing_dropdown.value}, f_smooth_width={freq_smooth_width_float.value}, resample={resample_hv_curve_bool.value}, verbose={verbose_check.value})""" process_hvsr_call.value='<style>p {word-wrap: break-word}</style> <p>' + ph_text + '</p>' #update_process_hvsr_call() def get_check_peaks_kwargs(): cp_kwargs = {'hvsr_band':hvsr_band_rangeSlide.value, 'peak_freq_range':peak_freq_rangeSlide.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_formats':['print','table'], 'plot_type':get_formatted_plot_str(), 'plot_engine':'plotly', 'report_export_path':None, 'csv_overwrite_opt':'overwrite', 'suppress_report_outputs':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_outliers_check.value=False use_hv_curve_outliers_check.disabled=False def get_rmse_range(): minRMSE = 10000 maxRMSE = -1 if roc_kwargs['use_hv_curves']: 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() outlier_threshold_slider.min = minRMSE outlier_threshold_slider.max = maxRMSE outlier_threshold_slider.step = round((maxRMSE-minRMSE)/100, 2) outlier_threshold_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_formats=['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_formats=['table']) results_table.value = hvsr_data['Table_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=comp, showlegend=True, 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, use_sprit_plot=True): global results_fig global results_subp hvsr_data = hv_data if use_sprit_plot: results_fig = sprit_plot.plot_results_plotly(hv_data=hv_data, plot_string=plot_string, azimuth='HV', results_fig=results_subp, results_graph_widget=results_fig, use_figure_widget=True, return_fig=True, show_results_plot=False, html_plot=False, verbose=verbose_check.value) else: 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.05, row_heights=[2, 1.5, 1.5]) 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) 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="PSD Amp\n[m2/s4/Hz][dB]", secondary_y=True, row=comp_plot_row, col=1) else: results_fig.update_yaxes(title_text="PSD Amp\n[m2/s4/Hz][dB]", row=comp_plot_row, col=1) if preview_fig.layout.width is None: if outlier_fig.layout.width is None: chartwidth = 1200 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}, width=chartwidth, showlegend=False, height = 0.5625 * float(chartwidth), title=f"{hvsr_data['site']} Results") # 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 = 2 log_textArea.value += f"\n\n{datetime.datetime.now()}\nResults Figure Updated: {plot_string}" hv_data["Plot_Report"] = results_fig 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", width=1200) 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_thresh=2, std_window_s=20, min_win_size=5 std_ratio_check = widgets.Checkbox(description='Standard Deviation Antitrigger (not yet implemented)', value=False, disabled=False, indent=False) std_ratio_thresh_text = widgets.FloatText(description='StdDev Ratio:', style={'description_width': 'initial'}, placeholder=2, value=2, layout=widgets.Layout(height='auto', width='auto'), disabled=False) std_window_length_text = widgets.FloatText(description='Moving window Length [s]:', style={'description_width': 'initial'}, placeholder=20, value=20, layout=widgets.Layout(height='auto', width='auto'),disabled=False) std_window_length_text = widgets.FloatText(description='Minimum Window Size [s]:', style={'description_width': 'initial'}, placeholder=2, value=2, layout=widgets.Layout(height='auto', width='auto'),disabled=False) #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={remove_method_select.value}, sat_percent={sat_percent_float.value}, noise_percent={noise_percent_float.value}, sta={sta_float.value}, lta={lta_float.value}, stalta_thresh={stalta_floatSlide.value}, warmup_time={warmup_time_int.value}, cooldown_time={cooldown_time_int.value}, min_win_size={min_win_size_float.value}, remove_raw_noise={raw_data_remove_check.value}, 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_thresh_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]) #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_psds_call = widgets.HTML(value='()') generate_ppsd_call_hbox = widgets.HBox([generate_ppsd_prefix, generate_psds_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]) 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_outlier_thresh_slider(change): if use_hv_curve_outliers_check.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 outlier_pctile_check.value: outlier_threshold_slider.value = outlier_threshold_slider.value else: outlier_threshold_slider.value = outlier_threshold_slider.value outlier_threshold_slider.value = ((rmse < outlier_threshold_slider.value).sum() / len(rmse)) * 100 def on_update_thresh_pctile_slider(change): if use_hv_curve_outliers_check.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 outlier_pctile_check.value: outlier_threshold_slider.value = np.percentile(rmse, outlier_threshold_slider.value) outlier_threshold_slider.value = outlier_threshold_slider.value else: outlier_threshold_slider.value = outlier_threshold_slider.value #outlier_threshold_chart_slider.observe(on_update_rmse_thresh_slider) #outlier_threshold_chart_slider.observe(on_update_rmse_pctile_slider) 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]) # Update remove_outlier call def update_remove_outlier_curve_call(): roc_text = f"""(hvsr_data=hvsr_data, outlier_method:{outlier_method_dropdown.value}, outlier_threshold={outlier_threshold_slider.value}, use_percentile={outlier_pctile_check.value}, min_pts:{min_pts_float.value}, use_hv_curves={use_hv_curve_outliers_check.value}, ... verbose={verbose_check.value})""" remove_outlier_curves_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) with outlier_graph_widget: display(outlier_fig) def update_outlier_fig(input=None, _rmse_thresh=outlier_threshold_slider.value, _use_percentile=True, _use_hv_curve=use_hv_curve_outliers_check.value, _verbose=verbose_check.value): global outlier_fig global hvsr_data hv_data = hvsr_data roc_kwargs = {'outlier_threshold':outlier_threshold_slider.value, 'use_percentile':True, 'use_hv_curves':use_hv_curve_outliers_check.value, 'plot_engine':'plotly', 'show_plot':False, 'verbose':verbose_check.value } if 'generate_psds_status' in hvsr_data.processing_status.keys() and hvsr_data.processing_status['generate_psds_status']: 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.processing_status['generate_psds_status']=False\n'{roc_kwargs}" return outlier_fig, hvsr_data if roc_kwargs['use_hv_curves']: 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['psds'][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['outlier_threshold']) # 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 # Update process_hvsr call def update_check_peaks_call(): #cp_kwargs = get_check_peaks_kwargs() cp_text = f"""(hvsr_data=hvsr_data, peak_selection={peak_selection_type.value}, hvsr_band={hvsr_band_rangeSlide.value}, peak_freq_range={peak_freq_rangeSlide.value}, 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_dropdown, freq_smooth_width_float]) #resample_hbox = widgets.HBox([resample_hv_curve_bool, resample_hv_curve]) #smooth_hbox = widgets.HBox([smooth_hv_curve_bool, smooth_hv_curve]) # 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=True, 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=True, 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=True, 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, plot_settings_tab]) #settings_tab = widgets.VBox(children=[settings_subtabs, settings_progress_hbox]) #settings_subtabs.set_title(0, "PSD Settings") #settings_subtabs.set_title(1, "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': from tkinter import tk, filedialog root = tk.Tk() root.wm_attributes('-topmost', True) root.withdraw() export_results_table_filepath.value = str(filedialog.asksaveasfilename(defaultextension='.csv', title='Save Table 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 if not hasattr(hvsr_results, "Table_Report"): sprit_hvsr.get_report(hvsr_results, report_formats=['table'], export_path=out_path, csv_overwrite_opt='overwrite') else: hvsr_results['Table_Report'].to_csv(out_path) export_results_table_browse_button.on_click(export_results_table) export_results_table_read_button.on_click(export_results_table) exportLabel = widgets.Label("Exports", layout=widgets.Layout(width='5%')) export_directory_text = widgets.Text(description="Directory", layout=widgets.Layout(width='50%'), value= pathlib.Path().home().as_posix()) export_data_button = widgets.Button(description='Data (.MSeed)', layout=widgets.Layout(width='10%')) export_report_button = widgets.Button(description="Report (.PDF)", layout=widgets.Layout(width='10%')) export_hvsr_button = widgets.Button(description="HVSR Data (.HVSR)", layout=widgets.Layout(width='10%')) export_subdirectories_check = widgets.Checkbox(description='Use Subfolders', value=True, layout=widgets.Layout(width='15%')) def on_export_data(event): hvID = '' if hasattr(hvsr_results, 'hvsr_id'): hvID = hvsr_results['hvsr_id'] nowTimeStr = datetime.datetime.now().strftime("%Y-%m-%d") export_dir = pathlib.Path(export_directory_text.value) if export_subdirectories_check.value: export_dir = export_dir.joinpath('Data') if not export_dir.exists(): export_dir.mkdir(parents=True) sprit_hvsr.export_data(hvsr_results, data_export_path=export_dir) print("Data exported successfully to: ", export_dir) def on_export_report(event): hvID = '' if hasattr(hvsr_results, 'hvsr_id'): hvID = hvsr_results['hvsr_id'] nowTimeStr = datetime.datetime.now().strftime("%Y-%m-%d") export_dir = pathlib.Path(export_directory_text.value) if export_subdirectories_check.value: export_dir = export_dir.joinpath('Reports') if not export_dir.exists(): export_dir.mkdir(parents=True) sprit_hvsr.export_report(hvsr_results, report_export_path=export_dir) print("Report exported successfully to: ", export_dir) def on_export_hvsr(event): hvID = '' if hasattr(hvsr_results, 'hvsr_id'): hvID = hvsr_results['hvsr_id'] nowTimeStr = datetime.datetime.now().strftime("%Y-%m-%d") export_dir = pathlib.Path(export_directory_text.value) if export_subdirectories_check.value: export_dir = export_dir.joinpath('HVSRFiles') if not export_dir.exists(): export_dir.mkdir(parents=True) sprit_hvsr.export_hvsr(hvsr_results, hvsr_export_path=export_dir) print("HVSR file exported successfully to: ", export_dir) export_data_button.on_click(on_export_data) export_report_button.on_click(on_export_report) export_hvsr_button.on_click(on_export_hvsr) 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]) results_export_hbox = widgets.HBox([exportLabel, export_directory_text, export_data_button, export_report_button, export_hvsr_button, export_subdirectories_check]) global results_tab plots_subtabs = widgets.Tab([results_graph_widget, plot_settings_tab]) plots_subtabs.set_title(0, "Plot Viewer") plots_subtabs.set_title(1, "Plot Settings") results_subtabs = widgets.Tab([plots_subtabs, printed_results_textArea, results_table_vbox]) results_tab = widgets.VBox(children=[results_subtabs, results_export_hbox]) 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, 'data_export_path': data_export_path_textbox, 'data_export_format': data_export_format_dropdown, 'detrend_type': detrend_type_dropdown, 'detrend_options': detrend_options, 'filter_type': filter_type_dropdown, 'filter_options': filter_options, 'update_metadata':update_metadata_checkbox.value, '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_float, 'special_handling':special_handling_dropdown, 'period_smoothing_width_octaves':period_smoothing_width, 'period_step_octaves':period_step_octave, 'period_limits':hvsr_band_rangeSlide}, 'process_hvsr': {'horizontal_method': h_combine_meth_dropdown, 'smooth': smooth_hv_curve, 'freq_smooth': freq_smoothing_dropdown, 'f_smooth_width': freq_smooth_width_float, 'resample': resample_hv_curve, 'verbose': verbose_check}, 'remove_outlier_curves': {'outlier_threshold': outlier_threshold_slider, 'use_percentile': outlier_pctile_check, 'use_hv_curves': use_hv_curve_outliers_check, 'verbose': verbose_check}, 'check_peaks': {'hvsr_band': hvsr_band_rangeSlide, 'peak_freq_range': peak_freq_rangeSlide, '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, results_tab, log_tab]) sprit_tabs.set_title(0, "Input") sprit_tabs.set_title(1, "Data View") sprit_tabs.set_title(2, "Results") sprit_tabs.set_title(3, "Log") with open(spritLogoPath.as_posix(), "rb") as file: image = file.read() sprit_logo = widgets.Image(value=image, format='png', width=30,height=30) sprit_title = widgets.Label(value='pRIT', 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_logo, sprit_title, sprit_subtitle, show_plot_check, verbose_check, 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], layout = widgets.Layout(align_content='space-between')) 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_psds_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)Function that generates the user interface for Jupyter Notebooks.
This interface uses ipywidgets, plotly, and IPython to create a user interface for processing data in a Jupyter notebook.
This is functionally equivalent to sprit.gui('nb').
See Also
gui