Skip to content

Allow long zone #163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,55 @@ cd spikeinterface-gui
pip install .
```

## Cedits
## Custom layout

You can create your own custom layout by specifying which views you'd like
to see, and where they go. The basic window layout supports eight "zones",
which are laid out as follows:

```
+-----------------+-----------------+
| [zone1 zone2] | [zone3 | [zone4 |
+-----------------+ | +
| [zone5 zone6] | zone7] | zone8] |
+-----------------+-----------------+
```

If zones are not included, the other zones take over their space. Hence if you'd
like to show waveforms as a long view, you can set zone3 to display waveforms
and then set zone7 to display nothing. The waveforms in zone3 will take over the
blank space from zone7.

To specify your own layout, put the specification in a `.json` file. This should
be a list of zones, and which views should appear in which zones. An example:


**my_layout.json**
```
{
"zone1": ["unitlist", "spikelist"],
"zone2": ["spikeamplitude"],
"zone3": ["waveform", "waveformheatmap"],
"zone4": ["similarity"],
"zone5": ["spikedepth"],
"zone6": [],
"zone7": [],
"zone8": ["correlogram"]
}
```

When you open spikeinterface-gui, you can then point to the `my_layout.json`
using the `--layout_file` flag:

```
sigui --layout_file=path/to/my_layout.json path/to/sorting_analyzer
```

Find a list of available views [in this file](https://github.com/SpikeInterface/spikeinterface-gui/blob/main/spikeinterface_gui/viewlist.py).



## Credits

Original author : Samuel Garcia, CNRS, Lyon, France

Expand Down
107 changes: 48 additions & 59 deletions spikeinterface_gui/backend_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,71 +277,60 @@ def create_main_layout(self):
))

# Create GridStack layout with resizable regions
grid_per_zone = 2
gs = pn.GridStack(
sizing_mode='stretch_both',
allow_resize=False,
allow_drag=False,
)

# Top modifications
for zone in ['zone1', 'zone2', 'zone3', 'zone4']:
view = layout_zone[zone]
row_slice = slice(0, 2 * grid_per_zone) # First two rows

if zone == 'zone1':
if layout_zone.get('zone2') is None or len(layout_zone['zone2']) == 0:
col_slice = slice(0, 2 * grid_per_zone) # Full width when merged
else:
col_slice = slice(0, grid_per_zone) # Half width when not merged
elif zone == 'zone2':
if layout_zone.get('zone1') is None or len(layout_zone['zone1']) == 0:
col_slice = slice(0, 2 * grid_per_zone) # Full width when merged
else:
col_slice = slice(grid_per_zone, 2 * grid_per_zone) # Right half
elif zone == 'zone3':
if layout_zone.get('zone4') is None or len(layout_zone['zone4']) == 0:
col_slice = slice(2 * grid_per_zone, 4 * grid_per_zone) # Full width when merged
else:
col_slice = slice(2 * grid_per_zone, 3 * grid_per_zone) # Left half
elif zone == 'zone4':
if layout_zone.get('zone3') is None or len(layout_zone['zone3']) == 0:
col_slice = slice(2 * grid_per_zone, 4 * grid_per_zone) # Full width when merged
else:
col_slice = slice(3 * grid_per_zone, 4 * grid_per_zone) # Right half

if view is not None and len(view) > 0:
# Note: order of slices swapped to [row, col]
gs[row_slice, col_slice] = view

# Bottom
for zone in ['zone5', 'zone6', 'zone7', 'zone8']:
view = layout_zone[zone]
row_slice = slice(2 * grid_per_zone, 4 * grid_per_zone)

if zone == 'zone5':
if layout_zone.get('zone6') is None or len(layout_zone['zone6']) == 0:
col_slice = slice(0, 2 * grid_per_zone)
else:
col_slice = slice(0, grid_per_zone)
elif zone == 'zone6':
if layout_zone.get('zone5') is None or len(layout_zone['zone5']) == 0:
col_slice = slice(0, 2 * grid_per_zone)
else:
col_slice = slice(grid_per_zone, 2 * grid_per_zone)
elif zone == 'zone7':
if layout_zone.get('zone8') is None or len(layout_zone['zone8']) == 0:
col_slice = slice(2 * grid_per_zone, 4 * grid_per_zone)
else:
col_slice = slice(2 * grid_per_zone, 3 * grid_per_zone)
elif zone == 'zone8':
if layout_zone.get('zone7') is None or len(layout_zone['zone7']) == 0:
col_slice = slice(2 * grid_per_zone, 4 * grid_per_zone)
else:
col_slice = slice(3 * grid_per_zone, 4 * grid_per_zone)

if view is not None and len(view) > 0:
gs[row_slice, col_slice] = view
all_zones = [f'zone{a}' for a in range(1,9)]
is_zone = [(layout_zone.get(zone) is not None) and (len(layout_zone.get(zone)) > 0) for zone in all_zones]

# Get number of columns and rows per sub-region
num_cols_12 = max(is_zone[0]*1 + is_zone[1]*1, is_zone[4]*1 + is_zone[5]*1)
num_cols_56 = num_cols_12
num_cols_37 = (is_zone[2] or is_zone[6])*1

num_rows_12 = ((is_zone[0] or is_zone[1])*1 - (is_zone[4] or is_zone[5])*1) + 1

# Do sub-regions [1,2], [4,5] [3][7] and [5][8] separately. For each, find out if
# both zones are present. If they are, place both in sub-region. If not, place one.

row_slice_12 = slice(0,num_rows_12)
if (is_zone[0] and is_zone[1]):
gs[row_slice_12, slice(0,1)] = layout_zone.get('zone1')
gs[row_slice_12, slice(1,2)] = layout_zone.get('zone2')
elif (is_zone[0] and not is_zone[1]):
gs[row_slice_12, slice(0,num_cols_12)] = layout_zone.get('zone1')
elif (is_zone[1] and not is_zone[0]):
gs[row_slice_12, slice(0,num_cols_12)] = layout_zone.get('zone2')

row_slice_56 = slice(num_rows_12, 2)
if (is_zone[4] and is_zone[5]):
gs[row_slice_56, slice(0,1)] = layout_zone.get('zone5')
gs[row_slice_56, slice(1,2)] = layout_zone.get('zone6')
elif (is_zone[4] and not is_zone[5]):
gs[row_slice_56, slice(0,num_cols_56)] = layout_zone.get('zone5')
elif (is_zone[5] and not is_zone[4]):
gs[row_slice_56, slice(0,num_cols_56)] = layout_zone.get('zone6')

col_slice_37 = slice(num_cols_12,num_cols_12+1)
if is_zone[2] and is_zone[6]:
gs[slice(0, 1), col_slice_37] = layout_zone.get('zone3')
gs[slice(1, 2), col_slice_37] = layout_zone.get('zone7')
elif is_zone[2] and not is_zone[6]:
gs[slice(0, 2), col_slice_37] = layout_zone.get('zone3')
elif is_zone[6] and not is_zone[2]:
gs[slice(0, 2), col_slice_37] = layout_zone.get('zone7')

col_slice_48 = slice(num_cols_12+num_cols_37,num_cols_12+num_cols_37+1)
if is_zone[3] and is_zone[7]:
gs[slice(0, 1), col_slice_48] = layout_zone.get('zone4')
gs[slice(1, 2), col_slice_48] = layout_zone.get('zone8')
elif is_zone[3] and not is_zone[7]:
gs[slice(0, 2), col_slice_48] = layout_zone.get('zone4')
elif is_zone[7] and not is_zone[3]:
gs[slice(0, 2), col_slice_48] = layout_zone.get('zone8')

self.main_layout = gs

Expand Down
22 changes: 11 additions & 11 deletions spikeinterface_gui/backend_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,25 +222,25 @@ def create_main_layout(self):
self.splitDockWidget(self.docks[first_left], dock, orientations['vertical'])

## Handle right
first_left = None
for zone in ['zone3', 'zone7', 'zone4', 'zone8']:
first_top = None
for zone in ['zone3', 'zone4', 'zone7', 'zone8']:
if len(widgets_zone[zone]) == 0:
continue
view_name = widgets_zone[zone][0]
dock = self.docks[view_name]
if len(widgets_zone[zone]) > 0 and first_left is None:
if len(widgets_zone[zone]) > 0 and first_top is None:
self.addDockWidget(areas['right'], dock)
first_left = view_name
elif zone == 'zone7':
self.splitDockWidget(self.docks[first_left], dock, orientations['vertical'])
first_top = view_name
elif zone == 'zone4':
self.splitDockWidget(self.docks[first_left], dock, orientations['horizontal'])
self.splitDockWidget(self.docks[first_top], dock, orientations['horizontal'])
elif zone == 'zone7':
self.splitDockWidget(self.docks[first_top], dock, orientations['vertical'])
elif zone == 'zone8':
if len(widgets_zone['zone7']) > 0:
z = widgets_zone['zone7'][0]
self.splitDockWidget(self.docks[z], dock, orientations['horizontal'])
if len(widgets_zone['zone4']) > 0:
z = widgets_zone['zone4'][0]
self.splitDockWidget(self.docks[z], dock, orientations['vertical'])
else:
self.splitDockWidget(self.docks[first_left], dock, orientations['vertical'])
self.splitDockWidget(self.docks[first_top], dock, orientations['horizontal'])

# make tabs
for zone, view_names in widgets_zone.items():
Expand Down
6 changes: 3 additions & 3 deletions spikeinterface_gui/layout_presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
A preset need 8 zones like this:

+-----------------+-----------------+
| [zone1 zone2] | [zone3 zone4] |
+-----------------+-----------------+
| [zone5 zone6] | [zone7 zone8] |
| [zone1 zone2] | [zone3 | [zone4 |
+-----------------+ | +
| [zone5 zone6] | zone7] | zone8] |
+-----------------+-----------------+

"""
Expand Down