Ejemplo n.º 1
0
def test_mainviewer():

    class FakeView(ViewerBase):
        def refresh(self):
            self.v = self.t
            #~ print('refresh', self.name, self.t)
            pass
        def set_settings(self, value):
            self.v = value
        def get_settings(self):
            return self.v

    app = ephyviewer.mkQApp()

    view1 = FakeView(name='view1')
    view2 = FakeView(name='view2')
    view3 = FakeView(name='view3')
    view4 = FakeView(name='view4')
    view5 = FakeView(name='view5')

    win = ephyviewer.MainViewer(settings_name='test0')
    win.add_view(view1)
    win.add_view(view2)

    win.add_view(view3, tabify_with='view2')
    win.add_view(view4, split_with='view1', orientation='horizontal')
    win.add_view(view5, location='bottom',  orientation='horizontal')

    win.show()
    app.exec_()
Ejemplo n.º 2
0
def test_neoviewer(interactive=False):
    from neo.rawio.tdtrawio import TdtRawIO

    local_test_dir = get_tdt_test_files()
    dirname = os.path.join(local_test_dir, 'aep_05')
    neorawio = TdtRawIO(dirname=dirname)
    neorawio.parse_header()
    print(neorawio)

    sources = ephyviewer.get_sources_from_neo_rawio(neorawio)

    app = ephyviewer.mkQApp()
    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)

    for i, sig_source in enumerate(sources['signal']):
        view = ephyviewer.TraceViewer(source=sig_source,
                                      name='signal {}'.format(i))
        win.add_view(view)

    for i, ep_source in enumerate(sources['epoch']):
        view = ephyviewer.EpochViewer(source=ep_source, name='epochs')
        win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 3
0
def test_neoviewer():
    #TODO make autorun neo tdtrawio test before
    from neo.rawio.tdtrawio import TdtRawIO

    dirname = '/tmp/files_for_testing_neo/tdt/aep_05/'
    neorawio = TdtRawIO(dirname=dirname)
    neorawio.parse_header()
    print(neorawio)

    sources = ephyviewer.get_sources_from_neo_rawio(neorawio)


    app = ephyviewer.mkQApp()
    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)

    for i, sig_source in enumerate(sources['signal']):
        view = ephyviewer.TraceViewer(source=sig_source, name='signal {}'.format(i))
        win.add_view(view)

    for i, ep_source in enumerate(sources['epoch']):
        view = ephyviewer.EpochViewer(source=ep_source, name='epochs')
        win.add_view(view)

    win.show()

    app.exec_()
Ejemplo n.º 4
0
    def open_ephyviewer(self):
        if self.win_viewer is not None:
            self.win_viewer.close()
            self.win_viewer = None

        if self.dataio is None:
            return
        if not hasattr(self.dataio.datasource, 'rawios'):
            return

        sources = ephyviewer.get_sources_from_neo_rawio(
            self.dataio.datasource.rawios[0])

        self.win_viewer = ephyviewer.MainViewer()

        for i, sig_source in enumerate(sources['signal']):
            view = ephyviewer.TraceViewer(source=sig_source,
                                          name='signal {}'.format(i))
            view.params['scale_mode'] = 'same_for_all'
            view.params['display_labels'] = True
            view.auto_scale()
            if i == 0:
                self.win_viewer.add_view(view)
            else:
                self.win_viewer.add_view(view,
                                         tabify_with='signal {}'.format(i - 1))

        self.win_viewer.show()
Ejemplo n.º 5
0
def test_mainviewer2():
    from  ephyviewer.tests.testing_tools import make_fake_video_source
    from  ephyviewer.tests.testing_tools import make_fake_signals
    from  ephyviewer.tests.testing_tools import make_fake_event_source
    from  ephyviewer.tests.testing_tools import make_fake_epoch_source


    app = ephyviewer.mkQApp()

    view1 = ephyviewer.TraceViewer(source=make_fake_signals(), name='signals')
    view2 = ephyviewer.VideoViewer(source=make_fake_video_source(), name='video')
    view3 = ephyviewer.EventList(source=make_fake_event_source(), name='events')
    view4 = ephyviewer.EpochViewer(source=make_fake_epoch_source(), name='epoch')
    view5 = ephyviewer.TimeFreqViewer(source=make_fake_signals(), name='timefreq')


    win = ephyviewer.MainViewer(debug=True, settings_name='test1', show_global_xsize=True, show_auto_scale=True)
    #TODO bug because new params!!!!!!!
    #~ win = ephyviewer.MainViewer(debug=True, show_global_xsize=True)
    win.add_view(view1)
    win.add_view(view5)
    win.add_view(view2)
    win.add_view(view4)
    win.add_view(view3, location='bottom',  orientation='horizontal')

    win.show()
    app.exec_()
Ejemplo n.º 6
0
def test_neoviewer(interactive=False):
    #~ from neo.rawio.tdtrawio import TdtRawIO

    #~ local_tdt_folder = get_tdt_test_files()
    #~ neorawio = TdtRawIO(dirname=local_tdt_folder)
    #~ neorawio.parse_header()
    #~ print(neorawio)

    from neo.rawio.blackrockrawio import BlackrockRawIO
    filename = get_blackrock_files()
    neorawio = BlackrockRawIO(filename=filename)
    neorawio.parse_header()
    print(neorawio)

    sources = ephyviewer.get_sources_from_neo_rawio(neorawio)
    print(sources)

    app = ephyviewer.mkQApp()
    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)

    for i, sig_source in enumerate(sources['signal']):
        view = ephyviewer.TraceViewer(source=sig_source,
                                      name='signal {}'.format(i))
        win.add_view(view)

    for i, ep_source in enumerate(sources['epoch']):
        view = ephyviewer.EpochViewer(source=ep_source, name='epochs')
        win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 7
0
def test_spikeinterface_viewer(interactive=False):
    import spikeinterface as si
    from spikeinterface.core.testing_tools import generate_recording, generate_sorting

    recording = generate_recording()
    sig_source = ephyviewer.SpikeInterfaceRecordingSource(recording=recording)

    sorting = generate_sorting()
    spike_source = ephyviewer.SpikeInterfaceSortingSource(sorting=sorting)

    app = ephyviewer.mkQApp()
    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)

    view = ephyviewer.TraceViewer(source=sig_source, name='signals')
    win.add_view(view)

    view = ephyviewer.SpikeTrainViewer(source=spike_source, name='spikes')
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 8
0
def test_EpochEncoder():
    possible_labels = ['AAA', 'BBB', 'CCC', 'DDD']

    ep_times = np.arange(0, 10., .5)
    ep_durations = np.ones(ep_times.shape) * .25
    ep_labels = np.random.choice(possible_labels, ep_times.size)
    epoch = {
        'time': ep_times,
        'duration': ep_durations,
        'label': ep_labels,
        'name': 'MyFactor'
    }

    source = WritableEpochSource(epoch=epoch, possible_labels=possible_labels)

    app = ephyviewer.mkQApp()
    view = ephyviewer.EpochEncoder(source=source, name='Epoch encoder')

    win = ephyviewer.MainViewer(show_step=False,
                                show_global_xsize=True,
                                debug=False)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 9
0
def test_epoch_viewer():
    source = make_fake_epoch_source()

    app = ephyviewer.mkQApp()
    view = ephyviewer.EpochViewer(source=source, name='epoch')

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 10
0
def test_traceviewer():
    source = make_fake_signals()

    app = ephyviewer.mkQApp()
    view = ephyviewer.TraceViewer(source=source, name='trace')
    #~ view.refresh()

    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 11
0
def test_eventlist():
    source = make_fake_event_source()


    app = ephyviewer.mkQApp()
    view = ephyviewer.EventList(source=source, name='events')

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 12
0
def test_spiketrain_viewer():
    source = make_fake_spiketrain_source()


    app = ephyviewer.mkQApp()
    view = ephyviewer.SpikeTrainViewer(source=source, name='spikes')

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 13
0
def test_traceviewer_cls_method_numpy():
    sigs = np.random.rand(100000, 16)
    sample_rate = 1000.
    t_start = 0.

    app = ephyviewer.mkQApp()
    view = ephyviewer.TraceViewer.from_numpy(sigs, sample_rate, t_start,
                                             'sigs')

    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)
    win.show()
    app.exec_()
Ejemplo n.º 14
0
def test_videoviewer():
    source = make_fake_video_source()

    #~ exit()
    #~ print('*'*50)
    app = ephyviewer.mkQApp()
    view = ephyviewer.VideoViewer(source=source, name='video')
    view.params['nb_column'] = 2

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 15
0
def test_eventlist(interactive=False):
    source = make_fake_event_source()

    app = ephyviewer.mkQApp()
    view = ephyviewer.EventList(source=source, name='events')

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 16
0
def test_traceviewer():
    source = make_fake_signals()

    app = ephyviewer.mkQApp()
    view = ephyviewer.TimeFreqViewer(source=source, name='timefreq')
    #~ view.refresh()

    #~ for c in range(source.nb_channel):
    #~ view.by_channel_params['ch'+str(c), 'visible'] = True

    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 17
0
def test_EpochEncoder_empty():
    possible_labels = ['AAA', 'BBB', 'CCC', 'DDD']

    source = WritableEpochSource(epoch=None, possible_labels=possible_labels)
    source._t_stop = 10  # set to positive value so navigation has a finite range

    app = ephyviewer.mkQApp()
    view = ephyviewer.EpochEncoder(source=source, name='Epoch encoder')

    win = ephyviewer.MainViewer(show_step=False,
                                show_global_xsize=True,
                                debug=False)
    win.add_view(view)
    win.show()

    app.exec_()
Ejemplo n.º 18
0
def test_dataframe_view():

    df = pd.DataFrame()
    df['time'] = np.arange(0, 10, .25)
    df['factorA'] = ['a', 'b', 'c', 'd'] * 10
    df['factorB'] = [10, 20] * 20
    df['quality'] = ['good', 'bad'] * 20

    app = ephyviewer.mkQApp()
    view = ephyviewer.DataFrameView(source=df, name='table')

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)
    win.show()

    app.exec_()
def test_spiketrain_viewer(interactive=False):
    source = make_fake_spiketrain_source()


    app = ephyviewer.mkQApp()
    view = ephyviewer.SpikeTrainViewer(source=source, name='spikes')

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 20
0
def test_save_load_params():
    from  ephyviewer.tests.testing_tools import make_fake_signals


    app = ephyviewer.mkQApp()

    view1 = ephyviewer.TraceViewer(source=make_fake_signals(), name='signals')

    win = ephyviewer.MainViewer(debug=True, settings_name='test2', show_global_xsize=True, show_auto_scale=True)
    #~ print(win.settings_name)
    #~ exit()
    #TODO bug because new params!!!!!!!
    win.add_view(view1)

    win.show()
    app.exec_()
Ejemplo n.º 21
0
def test_traceviewer_cls_method_numpy(interactive=False):
    sigs = np.random.rand(100000,16)
    sample_rate = 1000.
    t_start = 0.

    app = ephyviewer.mkQApp()
    view = ephyviewer.TraceViewer.from_numpy(sigs, sample_rate, t_start, 'sigs')

    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 22
0
def test_traceviewer(interactive=False):
    source = make_fake_signals()


    app = ephyviewer.mkQApp()
    view = ephyviewer.TraceViewer(source=source, name='trace')
    #~ view.refresh()


    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 23
0
def test_traceviewer_cls_method_neo():
    sigs = np.random.rand(100000, 16)
    sample_rate = 1000.
    t_start = 0.

    neo_anasig = neo.AnalogSignal(sigs * pq.mV,
                                  sampling_rate=sample_rate * pq.Hz,
                                  t_start=0 * pq.s,
                                  copy=True)
    print(neo_anasig)

    app = ephyviewer.mkQApp()

    view = ephyviewer.TraceViewer.from_neo_analogsignal(neo_anasig, 'sigs')
    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)
    win.show()
    app.exec_()
Ejemplo n.º 24
0
def test_videoviewer(interactive=False):
    source = make_fake_video_source()

    #~ exit()
    #~ print('*'*50)
    app = ephyviewer.mkQApp()
    view = ephyviewer.VideoViewer(source=source, name='video')
    view.params['nb_column'] = 2

    win = ephyviewer.MainViewer(debug=True)
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
def test_spectrogramviewer(interactive=False):

    app = ephyviewer.mkQApp()

    fs = sample_rate = 100000.
    times = np.arange(0, 100., 1. / sample_rate, dtype='float64')
    sigs = np.random.randn(times.size, 2) * 2.
    sigs[:, 0] += np.sin(times * 2 * np.pi * 5000.) * 1.5
    sigs[:, 1] += np.sin(times * 2 * np.pi * 20000.) * 0.5

    #create moving sinus
    sigsize = times.size
    f1 = 1000.
    f2 = 25000.
    freqs1 = np.concatenate([
        np.linspace(0, .5, sigsize * 3 // 8) * (f2 - f1) + f1,
        np.ones(sigsize // 4) * (f1 + f2) / 2,
        np.linspace(0, .5, sigsize * 3 // 8) * (f2 - f1) + (f1 + f2) / 2
    ],
                            axis=0)
    phase1 = np.cumsum(freqs1 / fs) * 2 * np.pi
    sigs[:, 0] += np.sin(phase1)

    t_start = 0.
    name = 'spectrogram'
    view = ephyviewer.SpectrogramViewer.from_numpy(sigs,
                                                   sample_rate,
                                                   t_start,
                                                   name,
                                                   channel_names=None)

    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)

    # view2 = ephyviewer.TraceViewer.from_numpy(sigs, sample_rate, t_start, 'sigs', channel_names=None)
    # win.add_view(view2)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 26
0
def test_timefreqviewer(interactive=False):
    source = make_fake_signals()

    app = ephyviewer.mkQApp()
    view = ephyviewer.TimeFreqViewer(source=source, name='timefreq')
    #~ view.refresh()

    #~ for c in range(source.nb_channel):
    #~ view.by_channel_params['ch'+str(c), 'visible'] = True

    win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)
    win.add_view(view)

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 27
0
def test_mainviewer(interactive=False):
    class FakeView(ViewerBase):
        def __init__(self, name=''):
            ViewerBase.__init__(self, name)
            self.v = None

        def refresh(self):
            self.v = self.t
            #~ print('refresh', self.name, self.t)
            pass

        def set_settings(self, value):
            self.v = value

        def get_settings(self):
            return self.v

    app = ephyviewer.mkQApp()

    view1 = FakeView(name='view1')
    view2 = FakeView(name='view2')
    view3 = FakeView(name='view3')
    view4 = FakeView(name='view4')
    view5 = FakeView(name='view5')

    win = ephyviewer.MainViewer(settings_name='test0')
    win.add_view(view1)
    win.add_view(view2)

    win.add_view(view3, tabify_with='view2')
    win.add_view(view4, split_with='view1', orientation='horizontal')
    win.add_view(view5, location='bottom', orientation='horizontal')

    if interactive:
        win.show()
        app.exec_()
    else:
        # close thread properly
        win.close()
Ejemplo n.º 28
0
from  ephyviewer.tests.testing_tools import make_fake_epoch_source

sig_source = make_fake_signals()
event_source = make_fake_event_source()
epoch_source = make_fake_epoch_source()
video_source = make_fake_video_source()



app = ephyviewer.mkQApp()
view1 = ephyviewer.TraceViewer(source=sig_source, name='signals')
view2 = ephyviewer.VideoViewer(source=video_source, name='video')
view3 = ephyviewer.EventList(source=event_source, name='events')
view4 = ephyviewer.EpochViewer(source=epoch_source, name='epoch')
view5 = ephyviewer.TimeFreqViewer(source=sig_source, name='timefreq')


win = ephyviewer.MainViewer(debug=True, settings_name='test1', show_global_xsize=True, show_auto_scale=True)

win.add_view(view1)
win.add_view(view5, split_with='signals')
win.add_view(view2)
win.add_view(view4)
win.add_view(view3, location='bottom',  orientation='horizontal')

win.show()

win.auto_scale()

app.exec_()
"""
import ephyviewer
import spikeinterface.full as si
from spikeinterface.core.testing_tools import generate_recording, generate_sorting

recording = generate_recording()
sig_source = ephyviewer.SpikeInterfaceRecordingSource(recording=recording)

filtered_recording = si.bandpass_filter(recording, freq_min=60., freq_max=100.)
sig_filtered_source = ephyviewer.SpikeInterfaceRecordingSource(
    recording=filtered_recording)

sorting = generate_sorting()
spike_source = ephyviewer.SpikeInterfaceSortingSource(sorting=sorting)

app = ephyviewer.mkQApp()
win = ephyviewer.MainViewer(debug=True, show_auto_scale=True)

view = ephyviewer.TraceViewer(source=sig_source, name='signals')
win.add_view(view)

view = ephyviewer.TraceViewer(source=sig_filtered_source,
                              name='signals filtered')
win.add_view(view)

view = ephyviewer.SpikeTrainViewer(source=spike_source, name='spikes')
win.add_view(view)

win.show()
app.exec_()
Ejemplo n.º 30
0
    def create_ephyviewer_window(self, theme='light', support_increased_line_width=False, show_datetime=False, datetime_format='%Y-%m-%d %H:%M:%S'):
        """
        Load data into each ephyviewer viewer and return the main window.
        """

        ########################################################################
        # DATA SOURCES

        seg = self.blk.segments[0]
        sigs = seg.analogsignals

        sources = {'signal': [], 'epoch': [], 'event': [], 'spike': []}
        sources['epoch'].append(ephyviewer.NeoEpochSource(seg.epochs))
        sources['event'].append(ephyviewer.NeoEventSource(seg.events))
        sources['spike'].append(ephyviewer.NeoSpikeTrainSource(seg.spiketrains))

        # filter epoch encoder data out of read-only epoch and event lists
        # so they are not presented multiple times, and remove empty channels
        sources['epoch'][0].all = [ep for ep in sources['epoch'][0].all if len(ep['time']) > 0 and '(from epoch encoder file)' not in ep['label']]
        sources['event'][0].all = [ev for ev in sources['event'][0].all if len(ev['time']) > 0 and '(from epoch encoder file)' not in ev['label']]

        ########################################################################
        # WINDOW

        # optionally display the real-world date and time
        if show_datetime and self.blk.rec_datetime is not None:
            show_label_datetime = True
            datetime0 = self.blk.rec_datetime
        else:
            show_label_datetime = False
            datetime0 = None

        # create a window that will be populated with viewers
        win = ephyviewer.MainViewer(
            # settings_name='test2', # remember settings (e.g. xsize) between sessions
            show_auto_scale = False,
            global_xsize_zoom = True,
            play_interval = 0.1, # refresh period in seconds
            show_label_datetime = show_label_datetime,
            datetime0 = datetime0,
            datetime_format = datetime_format,
        )
        win.setWindowTitle(self.metadata['key'])
        win.setWindowIcon(ephyviewer.QT.QIcon(':/neurotic-logo-150.png'))

        # delete on close so that memory and file resources are released
        win.setAttribute(ephyviewer.QT.WA_DeleteOnClose, True)

        ########################################################################
        # PREPARE TRACE PARAMETERS

        _set_defaults_for_plots(self.metadata, self.blk)

        plotNameToIndex = {p['channel']:i for i, p in enumerate(self.metadata['plots'])}

        ########################################################################
        # PREPARE SCATTER PLOT PARAMETERS

        if not self.lazy:
            all_times = sigs[0].times.rescale('s').magnitude # assuming all AnalogSignals have the same sampling rate and start time
            spike_indices = {}
            spike_channels = {}
            for st in seg.spiketrains:
                if 'channels' in st.annotations:
                    c = []
                    for channel in st.annotations['channels']:
                        index = plotNameToIndex.get(channel, None)
                        if index is None:
                            print('Note: Spike train {} will not be plotted on channel {} because that channel isn\'t being plotted'.format(st.name, channel))
                        else:
                            c.append(index)
                    if c:
                        spike_channels[st.name] = c
                        spike_indices[st.name] = np.where(np.isin(all_times, st.times.magnitude))[0]

        ########################################################################
        # TRACES WITH SCATTER PLOTS

        if self.is_shown('traces'):

            if self.lazy:
                import neo
                neorawioclass = neo.rawio.get_rawio_class(_abs_path(self.metadata, 'data_file'))
                if neorawioclass is None:
                    raise ValueError('This file type cannot be read with fast loading (lazy=True): {}'.format(_abs_path(self.metadata, 'data_file')))
                neorawio = neorawioclass(_abs_path(self.metadata, 'data_file'))
                neorawio.parse_header()

                # Intan-specific tricks
                if type(neorawio) is neo.rawio.IntanRawIO:
                    # dirty trick for getting ungrouped channels into a single source
                    neorawio.header['signal_channels']['group_id'] = 0

                    # prepare to append custom channel names stored in data file to ylabels
                    custom_channel_names = {c['native_channel_name']: c['custom_channel_name'] for c in neorawio._ordered_channels}

                channel_indexes = [p['index'] for p in self.metadata['plots']]
                sources['signal'].append(ephyviewer.AnalogSignalFromNeoRawIOSource(neorawio, channel_indexes))

                # modify loaded channel names to use ylabels
                for i, p in enumerate(self.metadata['plots']):

                    ylabel = p['ylabel']

                    # Intan-specific tricks
                    if type(neorawio) is neo.rawio.IntanRawIO:
                        # append custom channel names stored in data file to ylabels
                        if custom_channel_names[p['channel']] != ylabel:
                            ylabel += ' ({})'.format(custom_channel_names[p['channel']])

                    sources['signal'][-1].channels['name'][i] = ylabel

                # TODO support scatter
            else:
                sources['signal'].append(ephyviewer.AnalogSignalSourceWithScatter(
                    signals = np.concatenate([sigs[p['index']].magnitude for p in self.metadata['plots']], axis = 1),
                    sample_rate = sigs[0].sampling_rate, # assuming all AnalogSignals have the same sampling rate
                    t_start = sigs[0].t_start,           # assuming all AnalogSignals start at the same time
                    channel_names = [p['ylabel'] for p in self.metadata['plots']],
                    scatter_indexes = spike_indices,
                    scatter_channels = spike_channels,
                ))

            # useOpenGL=True eliminates the extremely poor performance associated
            # with TraceViewer's line_width > 1.0, but it also degrades overall
            # performance somewhat and is reportedly unstable
            if support_increased_line_width:
                useOpenGL = True
                line_width = 2.0
            else:
                useOpenGL = None
                line_width = 1.0

            trace_view = ephyviewer.TraceViewer(source = sources['signal'][0], name = 'signals', useOpenGL = useOpenGL)

            win.add_view(trace_view)

            trace_view.params['scatter_size'] = 5
            trace_view.params['line_width'] = line_width
            trace_view.params['display_labels'] = True
            trace_view.params['antialias'] = True

            # set the theme
            if theme != 'original':
                trace_view.params['background_color'] = self.themes[theme]['background_color']
                trace_view.params['vline_color'] = self.themes[theme]['vline_color']
                trace_view.params['label_fill_color'] = self.themes[theme]['label_fill_color']
                trace_view.params_controller.combo_cmap.setCurrentText(self.themes[theme]['cmap'])
                trace_view.params_controller.on_automatic_color()

            # adjust plot range, scaling, and positioning
            trace_view.params['ylim_max'] = 0.5
            trace_view.params['ylim_min'] = -trace_view.source.nb_channel + 0.5
            trace_view.params['scale_mode'] = 'by_channel'
            for i, p in enumerate(self.metadata['plots']):
                sig_units = sigs[p['index']].units
                units_ratio = (pq.Quantity(1, p['units'])/pq.Quantity(1, sig_units)).simplified
                assert units_ratio.dimensionality.string == 'dimensionless', f"Channel \"{p['channel']}\" has units {sig_units} and cannot be converted to {p['units']}"
                ylim_span = np.ptp(p['ylim'] * units_ratio.magnitude)
                ylim_center = np.mean(p['ylim'] * units_ratio.magnitude)
                trace_view.by_channel_params['ch{}'.format(i), 'gain'] = 1/ylim_span # rescale [ymin,ymax] across a unit
                trace_view.by_channel_params['ch{}'.format(i), 'offset'] = -i - ylim_center/ylim_span # center [ymin,ymax] within the unit

        ########################################################################
        # TRACES OF RAUC

        if self.is_shown('traces_rauc') and self.rauc_sigs is not None:

            sig_rauc_source = ephyviewer.InMemoryAnalogSignalSource(
                signals = np.concatenate([self.rauc_sigs[p['index']].as_array() for p in self.metadata['plots']], axis = 1),
                sample_rate = self.rauc_sigs[0].sampling_rate, # assuming all AnalogSignals have the same sampling rate
                t_start = self.rauc_sigs[0].t_start,           # assuming all AnalogSignals start at the same time
                channel_names = [p['ylabel'] + ' RAUC' for p in self.metadata['plots']],
            )
            sources['signal_rauc'] = [sig_rauc_source]

            trace_rauc_view = ephyviewer.TraceViewer(source = sources['signal_rauc'][0], name = 'signals rauc')

            if 'signals' in win.viewers:
                win.add_view(trace_rauc_view, tabify_with = 'signals')
            else:
                win.add_view(trace_rauc_view)

            trace_rauc_view.params['line_width'] = line_width
            trace_rauc_view.params['display_labels'] = True
            trace_rauc_view.params['display_offset'] = True
            trace_rauc_view.params['antialias'] = True

            # set the theme
            if theme != 'original':
                trace_rauc_view.params['background_color'] = self.themes[theme]['background_color']
                trace_rauc_view.params['vline_color'] = self.themes[theme]['vline_color']
                trace_rauc_view.params['label_fill_color'] = self.themes[theme]['label_fill_color']
                trace_rauc_view.params_controller.combo_cmap.setCurrentText(self.themes[theme]['cmap'])
                trace_rauc_view.params_controller.on_automatic_color()

            # adjust plot range
            trace_rauc_view.params['ylim_max'] = 0.5
            trace_rauc_view.params['ylim_min'] = -trace_rauc_view.source.nb_channel + 0.5
            trace_rauc_view.params['scale_mode'] = 'by_channel'
            for i, p in enumerate(self.metadata['plots']):
                ylim_span = np.median(self.rauc_sigs[p['index']].magnitude) * 10
                ylim_center = ylim_span / 2
                trace_rauc_view.by_channel_params['ch{}'.format(i), 'gain'] = 1/ylim_span # rescale [ymin,ymax] across a unit
                trace_rauc_view.by_channel_params['ch{}'.format(i), 'offset'] = -i - ylim_center/ylim_span # center [ymin,ymax] within the unit

        ########################################################################
        # FREQUENCY (EXPERIMENTAL AND COMPUTATIONALLY EXPENSIVE!)

        if self.is_shown('freqs'):

            freq_view = ephyviewer.TimeFreqViewer(source = trace_view.source, name = 'timefreqs')

            freq_view.params['scale_mode'] = 'by_channel'
            freq_view.params['nb_column'] = 1
            freq_view.params['colormap'] = 'gray'
            freq_view.params.param('timefreq')['deltafreq'] = 100
            freq_view.params.param('timefreq')['f_start'] = 1
            freq_view.params.param('timefreq')['f_stop'] = 1500

            freq_view.by_channel_params['ch0', 'visible'] = False
            freq_view.by_channel_params['ch1', 'visible'] = True
            freq_view.by_channel_params['ch2', 'visible'] = True
            freq_view.by_channel_params['ch3', 'visible'] = True
            freq_view.by_channel_params['ch4', 'visible'] = False

            # freq_view.params.param('timefreq')['normalisation'] = 1.5
            freq_view.by_channel_params['ch1', 'clim'] = 3
            freq_view.by_channel_params['ch2', 'clim'] = 5
            freq_view.by_channel_params['ch3', 'clim'] = 10

            if 'signals' in win.viewers:
                win.add_view(freq_view, tabify_with = 'signals')
            elif 'signals rauc' in win.viewers:
                win.add_view(freq_view, tabify_with = 'signals rauc')
            else:
                win.add_view(freq_view)

        ########################################################################
        # SPIKE TRAINS

        if self.is_shown('spike_trains') and sources['spike'][0].nb_channel > 0:

            spike_train_view = ephyviewer.SpikeTrainViewer(source = sources['spike'][0], name = 'spiketrains')
            win.add_view(spike_train_view)

            # set the theme
            if theme != 'original':
                spike_train_view.params['background_color'] = self.themes[theme]['background_color']
                spike_train_view.params['vline_color'] = self.themes[theme]['vline_color']
                spike_train_view.params['label_fill_color'] = self.themes[theme]['label_fill_color']
                spike_train_view.params_controller.combo_cmap.setCurrentText(self.themes[theme]['cmap'])
                spike_train_view.params_controller.on_automatic_color()

        ########################################################################
        # EPOCHS

        if self.is_shown('epochs') and sources['epoch'][0].nb_channel > 0:

            epoch_view = ephyviewer.EpochViewer(source = sources['epoch'][0], name = 'epochs')
            win.add_view(epoch_view)

            # set the theme
            if theme != 'original':
                epoch_view.params['background_color'] = self.themes[theme]['background_color']
                epoch_view.params['vline_color'] = self.themes[theme]['vline_color']
                epoch_view.params['label_fill_color'] = self.themes[theme]['label_fill_color']
                epoch_view.params_controller.combo_cmap.setCurrentText(self.themes[theme]['cmap'])
                epoch_view.params_controller.on_automatic_color()

        ########################################################################
        # EPOCH ENCODER

        if self.is_shown('epoch_encoder') and self.metadata['epoch_encoder_file'] is not None:

            possible_labels = self.metadata['epoch_encoder_possible_labels']

            # append labels found in the epoch encoder file but not in the
            # epoch_encoder_possible_labels list, preserving the original
            # ordering of epoch_encoder_possible_labels
            labels_from_file = [ep.name for ep in seg.epochs if len(ep.times) > 0 and '(from epoch encoder file)' in ep.labels]
            for label in labels_from_file:
                if label not in possible_labels:
                    possible_labels.append(label)

            writable_epoch_source = NeuroticWritableEpochSource(
                filename = _abs_path(self.metadata, 'epoch_encoder_file'),
                possible_labels = possible_labels,
            )

            epoch_encoder = ephyviewer.EpochEncoder(source = writable_epoch_source, name = 'epoch encoder')
            epoch_encoder.params['exclusive_mode'] = False
            win.add_view(epoch_encoder)

            # set the theme
            if theme != 'original':
                epoch_encoder.params['background_color'] = self.themes[theme]['background_color']
                epoch_encoder.params['vline_color'] = self.themes[theme]['vline_color']
                epoch_encoder.params['label_fill_color'] = self.themes[theme]['label_fill_color']
                # TODO add support for combo_cmap

        ########################################################################
        # VIDEO

        if self.is_shown('video') and self.metadata['video_file'] is not None:

            video_source = ephyviewer.MultiVideoFileSource(video_filenames = [_abs_path(self.metadata, 'video_file')])

            # some video files are loaded with an incorrect start time, so
            # reset video start to zero
            video_source.t_stops[0] -= video_source.t_starts[0]
            video_source.t_starts[0] = 0

            # apply the video_offset
            if self.metadata['video_offset'] is not None:
                video_source.t_starts[0] += self.metadata['video_offset']
                video_source.t_stops[0]  += self.metadata['video_offset']

            # correct for videos that report frame rates that are too fast or
            # too slow compared to the clock on the data acquisition system
            if self.metadata['video_rate_correction'] is not None:
                video_source.rates[0] *= self.metadata['video_rate_correction']

            if self.metadata['video_jumps'] is not None:

                # create an unmodified video_times vector with evenly spaced times
                video_times = np.arange(video_source.nb_frames[0])/video_source.rates[0] + video_source.t_starts[0]

                # insert repeating times at pause_start to fill pause_duration
                # so that that section of the video is skipped over
                for pause_start, pause_duration in self.metadata['video_jumps']:
                    pause_start_index = np.searchsorted(video_times, pause_start)
                    pause_fill = video_times[pause_start_index] * np.ones(int(np.round(pause_duration*video_source.rates[0])))
                    video_times = np.insert(video_times, pause_start_index, pause_fill)
                    video_times = video_times[:video_source.nb_frames[0]]

                # add the modified video_times to the video_source
                video_source.video_times = [video_times]
                video_source.t_starts[0] = min(video_times)
                video_source.t_stops[0]  = max(video_times)

            # update the source-level times from the modified file-level times
            video_source._t_start = max(min(video_source.t_starts), 0)
            video_source._t_stop  = max(video_source.t_stops)

            video_view = ephyviewer.VideoViewer(source = video_source, name = 'video')
            if theme != 'original':
                video_view.graphiclayout.setBackground(self.themes[theme]['background_color'])
            win.add_view(video_view, location = 'bottom', orientation = 'horizontal')

        ########################################################################
        # EVENTS

        if self.is_shown('event_list') and sources['event'][0].nb_channel > 0:

            event_list = ephyviewer.EventList(source = sources['event'][0], name = 'events')
            if 'video' in win.viewers:
                win.add_view(event_list, split_with = 'video')
            else:
                win.add_view(event_list, location = 'bottom', orientation = 'horizontal')

        ########################################################################
        # DATAFRAME

        annotations_dataframe = _neo_epoch_to_dataframe(seg.epochs, exclude_epoch_encoder_epochs=True)
        if self.is_shown('data_frame') and len(annotations_dataframe) > 0:

            data_frame_view = ephyviewer.DataFrameView(source = annotations_dataframe, name = 'table')
            if 'events' in win.viewers:
                win.add_view(data_frame_view, tabify_with = 'events')
            elif 'video' in win.viewers:
                win.add_view(data_frame_view, split_with = 'video')
            else:
                win.add_view(data_frame_view, location = 'bottom', orientation = 'horizontal')

        ########################################################################
        # FINAL TOUCHES

        # select first tabs
        for widget in win.children():
            if isinstance(widget, ephyviewer.PyQt5.QtWidgets.QTabBar):
                widget.setCurrentIndex(0)

        # set amount of time shown initially
        win.set_xsize(self.metadata['t_width']) # seconds

        return win