From 281255b9ae55ecd873c4524f15034af6253c7645 Mon Sep 17 00:00:00 2001 From: Camilo Diaz Date: Fri, 5 Apr 2024 14:58:28 -0400 Subject: [PATCH 1/6] ENH: added plot sets functionality STY: fixed typos in comments --- hnn_core/gui/_viz_manager.py | 99 +++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/hnn_core/gui/_viz_manager.py b/hnn_core/gui/_viz_manager.py index 5821ad22e..4c70ddea3 100644 --- a/hnn_core/gui/_viz_manager.py +++ b/hnn_core/gui/_viz_manager.py @@ -17,7 +17,6 @@ from hnn_core.gui._logging import logger from hnn_core.viz import plot_dipole - _fig_placeholder = 'Run simulation to add figures here.' _plot_types = [ @@ -68,7 +67,43 @@ "2row x 2col (1:1)": { "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", "mosaic": "01\n23", + } +} + +data_templates = { + "Drive-Dipole": { + "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "mosaic": "00\n11", + "ax_plots": [("ax0", "input histogram"), ("ax1", "current dipole")] + }, + "Dipole Layers": { + "kwargs": "gridspec_kw={\"height_ratios\":[1,1,1]}", + "mosaic": "0\n1\n2", + "ax_plots": [("ax0", "layer2 dipole"), ("ax1", "layer5 dipole"), + ("ax2", "current dipole")] + }, + "Drive-Spikes": { + "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "mosaic": "00\n11", + "ax_plots": [("ax0", "input histogram"), ("ax1", "spikes")] + }, + "Dipole-Spectrogram": { + "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "mosaic": "00\n11", + "ax_plots": [("ax0", "current dipole"), ("ax1", "spectrogram")] + }, + "Drive-Dipole-Spectrogram": { + "kwargs": "gridspec_kw={\"height_ratios\":[1,1,2]}", + "mosaic": "0\n1\n2", + "ax_plots": [("ax0", "input histogram"), ("ax1", "current dipole"), + ("ax2", "spectrogram")] }, + "PSD Layers": { + "kwargs": "gridspec_kw={\"height_ratios\":[1,1,1]}", + "mosaic": "0\n1\n2", + "ax_plots": [("ax0", "layer2 dipole"), ("ax1", "layer5 dipole"), + ("ax2", "PSD")] + } } @@ -87,6 +122,11 @@ def check_sim_plot_types( target_selection.value = 'None' +def check_templeta_type_is_data_dependant(template_name): + sim_data_options = list(data_templates.keys()) + return template_name in sim_data_options + + def target_comparison_change(new_target_name, simulation_selection, data): """Triggered when the target data is turned on or changed. """ @@ -636,8 +676,7 @@ def _add_axes_controls(widgets, data, fig, axd): widgets['axes_config_tabs'].set_title(n_tabs, _idx2figname(fig_idx)) -def _add_figure(b, widgets, data, scale=0.95, dpi=96): - template_name = widgets['templates_dropdown'].value +def _add_figure(b, widgets, data, template_type, scale=0.95, dpi=96): fig_idx = data['fig_idx']['idx'] viz_output_layout = data['visualization_output'] fig_outputs = Output() @@ -656,8 +695,8 @@ def _add_figure(b, widgets, data, scale=0.95, dpi=96): with fig_outputs: figsize = (scale * ((int(viz_output_layout.width[:-2]) - 10) / dpi), scale * ((int(viz_output_layout.height[:-2]) - 10) / dpi)) - mosaic = fig_templates[template_name]['mosaic'] - kwargs = eval(f"dict({fig_templates[template_name]['kwargs']})") + mosaic = template_type['mosaic'] + kwargs = eval(f"dict({template_type['kwargs']})") plt.ioff() fig, axd = plt.subplot_mosaic(mosaic, figsize=figsize, @@ -717,12 +756,15 @@ def __init__(self, gui_data, viz_layout): ) template_names = list(fig_templates.keys()) + template_names.extend(list(data_templates.keys())) self.templates_dropdown = Dropdown( description='Layout template:', options=template_names, value=template_names[0], style={'description_width': 'initial'}, layout=Layout(width="98%")) + self.templates_dropdown.observe(self.layout_template_change, 'value') + self.make_fig_button = Button( description='Make figure', button_style="primary", @@ -730,6 +772,14 @@ def __init__(self, gui_data, viz_layout): layout=self.viz_layout['btn']) self.make_fig_button.on_click(self.add_figure) + self.datasets_dropdown = Dropdown( + description='Dataset:', + options=[], + value=None, + style={'description_width': 'initial'}, + layout=Layout(width="98%")) + self.datasets_dropdown.layout.visibility = "hidden" + # data self.fig_idx = {"idx": 1} self.figs = {} @@ -741,7 +791,8 @@ def widgets(self): "figs_output": self.figs_output, "axes_config_tabs": self.axes_config_tabs, "figs_tabs": self.figs_tabs, - "templates_dropdown": self.templates_dropdown + "templates_dropdown": self.templates_dropdown, + "dataset_dropdown": self.datasets_dropdown } @property @@ -782,6 +833,7 @@ def compose(self): Box( [ self.templates_dropdown, + self.datasets_dropdown, self.make_fig_button, ], layout=Layout( @@ -795,16 +847,51 @@ def compose(self): ]) return config_panel, fig_output_container + def layout_template_change(self, template_type): + # check if plot set type requires loaded sim-data + if check_templeta_type_is_data_dependant(template_type.new): + sim_names = [ + sim for sim in self.data["simulations"] + ] + self.datasets_dropdown.options = sim_names + self.datasets_dropdown.value = sim_names[0] + # show list of simulated or loaded data + self.datasets_dropdown.layout.visibility = "visible" + else: + # hide sim-data dropdown + self.datasets_dropdown.layout.visibility = "hidden" + @unlink_relink(attribute='figs_config_tab_link') def add_figure(self, b=None): """Add a figure and corresponding config tabs to the dashboard. """ + template_name = self.widgets['templates_dropdown'].value + is_data_template = check_templeta_type_is_data_dependant(template_name) + # if it's a data dependent layout use data_templates dictionary + template_type = (fig_templates[template_name] + if not is_data_template + else data_templates[template_name]) + + # set up plot fig according to template params _add_figure(None, self.widgets, self.data, + template_type, scale=0.97, dpi=self.viz_layout['dpi']) + # check if plotting a data dependent template fig + num_data_sims = len(self.data["simulations"]) + if is_data_template and num_data_sims > 0: + sim_name = self.widgets["dataset_dropdown"].value + fig_name = _idx2figname(self.data['fig_idx']['idx'] - 1) + # get figs per axis + ax_plots = data_templates[template_name]["ax_plots"] + for ax_name, plot_type in ax_plots: + # paint fig in axis + self._simulate_edit_figure(fig_name, ax_name, sim_name, + plot_type, {}, "plot") + def _simulate_add_fig(self): self.make_fig_button.click() From 379c3d49d320e2073a520b535ea6412198283354 Mon Sep 17 00:00:00 2001 From: Camilo Diaz Date: Wed, 10 Apr 2024 14:32:44 -0400 Subject: [PATCH 2/6] ENH: Added Blank to empty plot templates. Checking only simulations are in the dropdown DOC: Fixing gui layout template name STY: Fixing typo in a function naming --- doc/gui/tutorial_erp.ipynb | 2 +- hnn_core/gui/_viz_manager.py | 33 +++++++++++++++++++-------------- hnn_core/gui/gui.py | 3 ++- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/doc/gui/tutorial_erp.ipynb b/doc/gui/tutorial_erp.ipynb index 04359d5ee..27d5fea74 100644 --- a/doc/gui/tutorial_erp.ipynb +++ b/doc/gui/tutorial_erp.ipynb @@ -362,7 +362,7 @@ "metadata": {}, "outputs": [], "source": [ - "gui._simulate_viz_action('switch_fig_template', 'single figure')\n", + "gui._simulate_viz_action('switch_fig_template', '[Blank] single figure')\n", "gui._simulate_viz_action('add_fig')\n", "gui._simulate_viz_action(\n", " \"edit_figure\",\n", diff --git a/hnn_core/gui/_viz_manager.py b/hnn_core/gui/_viz_manager.py index 4c70ddea3..256959f33 100644 --- a/hnn_core/gui/_viz_manager.py +++ b/hnn_core/gui/_viz_manager.py @@ -48,23 +48,23 @@ ] fig_templates = { - "2row x 1col (1:3)": { + "[Blank] 2row x 1col (1:3)": { "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", "mosaic": "00\n11", }, - "2row x 1col (1:1)": { + "[Blank] 2row x 1col (1:1)": { "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", "mosaic": "00\n11", }, - "1row x 2col (1:1)": { + "[Blank] 1row x 2col (1:1)": { "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", "mosaic": "01\n01", }, - "single figure": { + "[Blank] single figure": { "kwargs": "", "mosaic": "00\n00", }, - "2row x 2col (1:1)": { + "[Blank] 2row x 2col (1:1)": { "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", "mosaic": "01\n23", } @@ -122,7 +122,7 @@ def check_sim_plot_types( target_selection.value = 'None' -def check_templeta_type_is_data_dependant(template_name): +def check_template_type_is_data_dependant(template_name): sim_data_options = list(data_templates.keys()) return template_name in sim_data_options @@ -755,8 +755,8 @@ def __init__(self, gui_data, viz_layout): (self.figs_tabs, 'selected_index'), ) - template_names = list(fig_templates.keys()) - template_names.extend(list(data_templates.keys())) + template_names = list(data_templates.keys()) + template_names.extend(list(fig_templates.keys())) self.templates_dropdown = Dropdown( description='Layout template:', options=template_names, @@ -849,13 +849,18 @@ def compose(self): def layout_template_change(self, template_type): # check if plot set type requires loaded sim-data - if check_templeta_type_is_data_dependant(template_type.new): - sim_names = [ - sim for sim in self.data["simulations"] - ] + if check_template_type_is_data_dependant(template_type.new): + # Add only simualated data + sim_names = [simulations for simulations, sim_name + in self.data["simulations"].items() + if sim_name['net'] is not None] + + if len(sim_names) == 0: + sim_names = [" "] + self.datasets_dropdown.options = sim_names self.datasets_dropdown.value = sim_names[0] - # show list of simulated or loaded data + # show list of simulated to gui dropdown self.datasets_dropdown.layout.visibility = "visible" else: # hide sim-data dropdown @@ -866,7 +871,7 @@ def add_figure(self, b=None): """Add a figure and corresponding config tabs to the dashboard. """ template_name = self.widgets['templates_dropdown'].value - is_data_template = check_templeta_type_is_data_dependant(template_name) + is_data_template = check_template_type_is_data_dependant(template_name) # if it's a data dependent layout use data_templates dictionary template_type = (fig_templates[template_name] if not is_data_template diff --git a/hnn_core/gui/gui.py b/hnn_core/gui/gui.py index 9870040f9..5df741116 100644 --- a/hnn_core/gui/gui.py +++ b/hnn_core/gui/gui.py @@ -1143,7 +1143,8 @@ def on_upload_data_change(change, data, viz_manager, log_out): hnn_core.read_dipole(io.StringIO(ext_content)) ]} logger.info(f'External data {data_fname} loaded.') - viz_manager.reset_fig_config_tabs(template_name='single figure') + _template_name = "[Blank] single figure" + viz_manager.reset_fig_config_tabs(template_name=_template_name) viz_manager.add_figure() fig_name = _idx2figname(viz_manager.data['fig_idx']['idx'] - 1) ax_plots = [("ax0", "current dipole")] From ebc38ee28dcfbaf7ad150b6f8df0750cee841118 Mon Sep 17 00:00:00 2001 From: Camilo Diaz Date: Thu, 11 Apr 2024 16:34:54 -0400 Subject: [PATCH 3/6] MAINT: refactoring add_figure logic on data dependant layouts --- hnn_core/gui/_viz_manager.py | 34 +++++++++++++++++++++++----------- hnn_core/gui/gui.py | 2 ++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/hnn_core/gui/_viz_manager.py b/hnn_core/gui/_viz_manager.py index 256959f33..192255811 100644 --- a/hnn_core/gui/_viz_manager.py +++ b/hnn_core/gui/_viz_manager.py @@ -778,7 +778,6 @@ def __init__(self, gui_data, viz_layout): value=None, style={'description_width': 'initial'}, layout=Layout(width="98%")) - self.datasets_dropdown.layout.visibility = "hidden" # data self.fig_idx = {"idx": 1} @@ -870,14 +869,24 @@ def layout_template_change(self, template_type): def add_figure(self, b=None): """Add a figure and corresponding config tabs to the dashboard. """ + if len(self.data["simulations"]) == 0: + logger.error("No data has been loaded") + return + template_name = self.widgets['templates_dropdown'].value is_data_template = check_template_type_is_data_dependant(template_name) - # if it's a data dependent layout use data_templates dictionary - template_type = (fig_templates[template_name] - if not is_data_template - else data_templates[template_name]) + if is_data_template: + sim_name = self.widgets["dataset_dropdown"].value + if sim_name not in self.data["simulations"]: + logger.error("No simulation data has been loaded") + return - # set up plot fig according to template params + # Use data_templates dictionary if it's a data dependent layout + template_type = (data_templates[template_name] + if is_data_template + else fig_templates[template_name]) + + # Add empty figure according to template arguments _add_figure(None, self.widgets, self.data, @@ -885,10 +894,8 @@ def add_figure(self, b=None): scale=0.97, dpi=self.viz_layout['dpi']) - # check if plotting a data dependent template fig - num_data_sims = len(self.data["simulations"]) - if is_data_template and num_data_sims > 0: - sim_name = self.widgets["dataset_dropdown"].value + # Check if plotting a data dependent template figure + if is_data_template: fig_name = _idx2figname(self.data['fig_idx']['idx'] - 1) # get figs per axis ax_plots = data_templates[template_name]["ax_plots"] @@ -896,12 +903,17 @@ def add_figure(self, b=None): # paint fig in axis self._simulate_edit_figure(fig_name, ax_name, sim_name, plot_type, {}, "plot") + logger.info(f"Figure {template_name} for " + f"simulation {sim_name} " + "has been created" + ) def _simulate_add_fig(self): self.make_fig_button.click() def _simulate_switch_fig_template(self, template_name): - assert template_name in fig_templates.keys(), "No such template" + assert (template_name in fig_templates.keys() or + data_templates.keys()), "No such template" self.templates_dropdown.value = template_name def _simulate_delete_figure(self, fig_name): diff --git a/hnn_core/gui/gui.py b/hnn_core/gui/gui.py index 5df741116..add4ee269 100644 --- a/hnn_core/gui/gui.py +++ b/hnn_core/gui/gui.py @@ -1148,6 +1148,8 @@ def on_upload_data_change(change, data, viz_manager, log_out): viz_manager.add_figure() fig_name = _idx2figname(viz_manager.data['fig_idx']['idx'] - 1) ax_plots = [("ax0", "current dipole")] + + # these lines plot the data per axis for ax_name, plot_type in ax_plots: viz_manager._simulate_edit_figure( fig_name, ax_name, data_fname, plot_type, {}, "plot") From 056820146523a410d3f61b8b2c123c1da9ebe479 Mon Sep 17 00:00:00 2001 From: Camilo Diaz Date: Thu, 11 Apr 2024 17:10:32 -0400 Subject: [PATCH 4/6] MAINT: Refactored layout templates properties MAINT: changed new functions to private. Adding grid specs for new data templates --- hnn_core/gui/_viz_manager.py | 69 ++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/hnn_core/gui/_viz_manager.py b/hnn_core/gui/_viz_manager.py index 192255811..2ccceb99a 100644 --- a/hnn_core/gui/_viz_manager.py +++ b/hnn_core/gui/_viz_manager.py @@ -49,57 +49,79 @@ fig_templates = { "[Blank] 2row x 1col (1:3)": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 3]} + }, "mosaic": "00\n11", }, "[Blank] 2row x 1col (1:1)": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1]} + }, "mosaic": "00\n11", }, "[Blank] 1row x 2col (1:1)": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1]} + }, "mosaic": "01\n01", }, "[Blank] single figure": { - "kwargs": "", + "kwargs": { + "gridspec_kw": "" + }, "mosaic": "00\n00", }, "[Blank] 2row x 2col (1:1)": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,1]}", + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1]} + }, "mosaic": "01\n23", } } data_templates = { - "Drive-Dipole": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "Drive-Dipole (2X1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 3]} + }, "mosaic": "00\n11", "ax_plots": [("ax0", "input histogram"), ("ax1", "current dipole")] }, - "Dipole Layers": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,1,1]}", + "Dipole Layers (3x1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1, 1]} + }, "mosaic": "0\n1\n2", "ax_plots": [("ax0", "layer2 dipole"), ("ax1", "layer5 dipole"), ("ax2", "current dipole")] }, - "Drive-Spikes": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "Drive-Spikes (2x1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 3]} + }, "mosaic": "00\n11", "ax_plots": [("ax0", "input histogram"), ("ax1", "spikes")] }, - "Dipole-Spectrogram": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,3]}", + "Dipole-Spectrogram (2x1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 3]} + }, "mosaic": "00\n11", "ax_plots": [("ax0", "current dipole"), ("ax1", "spectrogram")] }, - "Drive-Dipole-Spectrogram": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,1,2]}", + "Drive-Dipole-Spectrogram (3x1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1, 2]} + }, "mosaic": "0\n1\n2", "ax_plots": [("ax0", "input histogram"), ("ax1", "current dipole"), ("ax2", "spectrogram")] }, - "PSD Layers": { - "kwargs": "gridspec_kw={\"height_ratios\":[1,1,1]}", + "PSD Layers (3x1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1, 1]} + }, "mosaic": "0\n1\n2", "ax_plots": [("ax0", "layer2 dipole"), ("ax1", "layer5 dipole"), ("ax2", "PSD")] @@ -122,7 +144,7 @@ def check_sim_plot_types( target_selection.value = 'None' -def check_template_type_is_data_dependant(template_name): +def _check_template_type_is_data_dependant(template_name): sim_data_options = list(data_templates.keys()) return template_name in sim_data_options @@ -696,7 +718,7 @@ def _add_figure(b, widgets, data, template_type, scale=0.95, dpi=96): figsize = (scale * ((int(viz_output_layout.width[:-2]) - 10) / dpi), scale * ((int(viz_output_layout.height[:-2]) - 10) / dpi)) mosaic = template_type['mosaic'] - kwargs = eval(f"dict({template_type['kwargs']})") + kwargs = template_type['kwargs'] plt.ioff() fig, axd = plt.subplot_mosaic(mosaic, figsize=figsize, @@ -763,7 +785,7 @@ def __init__(self, gui_data, viz_layout): value=template_names[0], style={'description_width': 'initial'}, layout=Layout(width="98%")) - self.templates_dropdown.observe(self.layout_template_change, 'value') + self.templates_dropdown.observe(self._layout_template_change, 'value') self.make_fig_button = Button( description='Make figure', @@ -846,9 +868,9 @@ def compose(self): ]) return config_panel, fig_output_container - def layout_template_change(self, template_type): + def _layout_template_change(self, template_type): # check if plot set type requires loaded sim-data - if check_template_type_is_data_dependant(template_type.new): + if _check_template_type_is_data_dependant(template_type.new): # Add only simualated data sim_names = [simulations for simulations, sim_name in self.data["simulations"].items() @@ -874,7 +896,8 @@ def add_figure(self, b=None): return template_name = self.widgets['templates_dropdown'].value - is_data_template = check_template_type_is_data_dependant(template_name) + is_data_template = (_check_template_type_is_data_dependant + (template_name)) if is_data_template: sim_name = self.widgets["dataset_dropdown"].value if sim_name not in self.data["simulations"]: From bed7eea3fed15faa06359797375c82b470d72739 Mon Sep 17 00:00:00 2001 From: Camilo Diaz Date: Fri, 12 Apr 2024 15:17:02 -0400 Subject: [PATCH 5/6] TST: Addded test of data dependant layout templates STY: Fixed typo in test docustring MAINT: pythonizing for loop on list of tuples DOC: Added plot sets feature to whats_new.rst docs: Removed ipywidgets version and added note pointing to GUI installation section. --- doc/whats_new.rst | 3 +++ hnn_core/gui/_viz_manager.py | 2 +- hnn_core/tests/test_gui.py | 39 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/doc/whats_new.rst b/doc/whats_new.rst index d9f0f04a4..fe5037582 100644 --- a/doc/whats_new.rst +++ b/doc/whats_new.rst @@ -48,6 +48,9 @@ Changelog - Added kwargs options to `plot_spikes_hist` for adjusting the histogram plots of spiking activity, by `Abdul Samad Siddiqui`_ in :gh:`732`. + +- Added pre defined plot sets for simulated data, + by `Camilo Diaz`_ in :gh:`746` Bug ~~~ diff --git a/hnn_core/gui/_viz_manager.py b/hnn_core/gui/_viz_manager.py index 2ccceb99a..4fb53eaae 100644 --- a/hnn_core/gui/_viz_manager.py +++ b/hnn_core/gui/_viz_manager.py @@ -81,7 +81,7 @@ } data_templates = { - "Drive-Dipole (2X1)": { + "Drive-Dipole (2x1)": { "kwargs": { "gridspec_kw": {"height_ratios": [1, 3]} }, diff --git a/hnn_core/tests/test_gui.py b/hnn_core/tests/test_gui.py index 423a7afa6..595e6b76e 100644 --- a/hnn_core/tests/test_gui.py +++ b/hnn_core/tests/test_gui.py @@ -338,6 +338,45 @@ def test_gui_add_figure(): plt.close('all') +def test_gui_add_data_dependent_figure(): + """Test if the GUI adds/deletes figs data dependent properly.""" + gui = HNNGUI() + _ = gui.compose() + gui.params['N_pyr_x'] = 3 + gui.params['N_pyr_y'] = 3 + + fig_tabs = gui.viz_manager.figs_tabs + axes_config_tabs = gui.viz_manager.axes_config_tabs + assert len(fig_tabs.children) == 0 + assert len(axes_config_tabs.children) == 0 + + # after each run we should have a default fig + gui.run_button.click() + assert len(fig_tabs.children) == 1 + assert len(axes_config_tabs.children) == 1 + assert gui.viz_manager.fig_idx['idx'] == 2 + + template_names = [('Drive-Dipole (2x1)', 2), + ('Dipole Layers (3x1)', 3), + ('Drive-Spikes (2x1)', 2), + ('Dipole-Spectrogram (2x1)', 2), + ('Drive-Dipole-Spectrogram (3x1)', 3), + ('PSD Layers (3x1)', 3)] + + n_fig = 1 + for template_name, num_axes in template_names: + gui.viz_manager.templates_dropdown.value = template_name + assert len(gui.viz_manager.datasets_dropdown.options) == 1 + gui.viz_manager.make_fig_button.click() + # Check figs have data on their axis + for ax in range(num_axes): + assert gui.viz_manager.figs[n_fig + 1].axes[ax].has_data() + n_fig = n_fig + 1 + + # test number of created figures + assert len(fig_tabs.children) == n_fig + + def test_gui_edit_figure(): """Test if the GUI adds/deletes figs properly.""" gui = HNNGUI() From 327a3a66345910ab91b43f6b5357c0dd1926e038 Mon Sep 17 00:00:00 2001 From: Camilo Diaz Date: Wed, 17 Apr 2024 18:45:21 -0400 Subject: [PATCH 6/6] ENH: Added Dipole-Spikes plot --- hnn_core/gui/_viz_manager.py | 9 ++++++++- hnn_core/tests/test_gui.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/hnn_core/gui/_viz_manager.py b/hnn_core/gui/_viz_manager.py index 4fb53eaae..afd8a0c73 100644 --- a/hnn_core/gui/_viz_manager.py +++ b/hnn_core/gui/_viz_manager.py @@ -110,6 +110,13 @@ "mosaic": "00\n11", "ax_plots": [("ax0", "current dipole"), ("ax1", "spectrogram")] }, + "Dipole-Spikes (2x1)": { + "kwargs": { + "gridspec_kw": {"height_ratios": [1, 1]} + }, + "mosaic": "00\n11", + "ax_plots": [("ax0", "current dipole"), ("ax1", "spikes")] + }, "Drive-Dipole-Spectrogram (3x1)": { "kwargs": { "gridspec_kw": {"height_ratios": [1, 1, 2]} @@ -917,7 +924,7 @@ def add_figure(self, b=None): scale=0.97, dpi=self.viz_layout['dpi']) - # Check if plotting a data dependent template figure + # Plot data if it is a data-dependent template if is_data_template: fig_name = _idx2figname(self.data['fig_idx']['idx'] - 1) # get figs per axis diff --git a/hnn_core/tests/test_gui.py b/hnn_core/tests/test_gui.py index 595e6b76e..965991110 100644 --- a/hnn_core/tests/test_gui.py +++ b/hnn_core/tests/test_gui.py @@ -360,6 +360,7 @@ def test_gui_add_data_dependent_figure(): ('Dipole Layers (3x1)', 3), ('Drive-Spikes (2x1)', 2), ('Dipole-Spectrogram (2x1)', 2), + ("Dipole-Spikes (2x1)", 2), ('Drive-Dipole-Spectrogram (3x1)', 3), ('PSD Layers (3x1)', 3)]