コード例 #1
0
    def test_to_ptsa(self, which):
        data = np.random.random((10, 32, 100))
        rate = 1000

        if which == "epochs":
            epochs = [(i, i + 100) for i in range(data.shape[0])]
            ts = EEGContainer(data, rate, epochs=epochs)
        else:
            filename = resource_filename("cmlreaders.test.data",
                                         "R1111M_FR1_0_events.json")
            events = pd.read_json(filename).iloc[:data.shape[0]]
            ts = EEGContainer(data, rate, events=events)

        tsx = ts.to_ptsa()

        assert isinstance(tsx, TimeSeries)
        assert tsx["samplerate"] == ts.samplerate
        assert_equal(tsx.data, data)

        offsets = tsx["event"].data["eegoffset"]

        if which == "epochs":
            assert_equal(offsets, ts.start_offsets)
        else:
            assert_equal(offsets, events["eegoffset"])

        assert_equal(tsx["time"].data, ts.time)
コード例 #2
0
    def test_concatenate(self, dim):
        n_channels = 32
        n_samples = 100
        rate = 1000

        data = [
            np.random.random((1, n_channels, n_samples)),
            np.random.random((1, n_channels, n_samples)),
        ]

        def get_tstart(i):
            if dim == "time":
                return (i * n_samples) / rate * 1000
            else:
                return 0

        series = [
            EEGContainer(d, rate, tstart=get_tstart(i), attrs={'test': 'me'})
            for i, d in enumerate(data)
        ]

        ts = EEGContainer.concatenate(series, dim=dim)

        if dim == "events":
            assert ts.shape == (2, n_channels, n_samples)
            assert_equal(ts.data, np.concatenate(data, axis=0))
        elif dim == "time":
            assert ts.shape == (1, n_channels, n_samples * 2)
            assert_equal(ts.data, np.concatenate(data, axis=2))
コード例 #3
0
 def test_resample(self):
     x = np.linspace(0, 4 * np.pi, 400)
     data = np.sin([x, x])
     ts = EEGContainer(data, 100)
     new_ts = ts.resample(200)
     assert len(new_ts.time) == 2 * len(ts.time)
     assert (new_ts.time[1] - new_ts.time[0]) * 2 == \
            (ts.time[1] - ts.time[0])
コード例 #4
0
    def test_create_channels(self):
        data = np.random.random((11, 32, 100))
        contacts = [i + 1 for i in range(data.shape[1])]

        ts = EEGContainer(data, 1000, channels=contacts)
        assert ts.channels == contacts

        with pytest.raises(ValueError):
            EEGContainer(data, 1000, channels=[1, 2])
コード例 #5
0
    def test_create_epochs(self, data):
        good_epochs = [(0, 100)]
        bad_epochs = [(0, 100), (100, 200)]

        ts = EEGContainer(data, 1000, epochs=good_epochs)
        assert ts.epochs == good_epochs

        with pytest.raises(ValueError):
            EEGContainer(data, 1000, epochs=bad_epochs)
コード例 #6
0
    def test_create_defaults(self, data):
        if len(data.shape) < 2:
            with pytest.raises(ValueError):
                EEGContainer(data, 1000)
            return

        ts = EEGContainer(data, 1000)

        assert ts.shape == ts.data.shape

        for epoch in ts.epochs:
            assert epoch == (-1, -1)

        assert_equal(ts.channels, [i + 1 for i in range(ts.data.shape[1])])
コード例 #7
0
    def test_to_mne(self):
        events = int(np.random.uniform(1, 10))
        channels = int(np.random.uniform(1, 128))
        samples = int(np.random.uniform(10, 100))

        data = np.random.random((events, channels, samples))
        rate = 1000
        ts = EEGContainer(data, rate)
        ea = ts.to_mne()

        assert len(ea.times) == samples
        assert len(ea.events) == events
        assert len(ea.info['chs']) == channels
        assert_equal(ea.get_data().shape, data.shape)
コード例 #8
0
    def make_eeg(self, events, rel_start, rel_stop):
        """Fake EEG data for testing without rhino."""
        from cmlreaders.eeg_container import EEGContainer

        channels = ["CH{}".format(n) for n in range(1, 10)]
        data = np.random.random(
            (len(events), len(channels), rel_stop - rel_start))

        container = EEGContainer(data, 1000, events=events, channels=channels)

        return container
コード例 #9
0
    def as_timeseries(self, events: pd.DataFrame,
                      rel_start: Union[float, int],
                      rel_stop: Union[float, int]) -> EEGContainer:
        """Read the timeseries.

        Parameters
        ----------
        events
            Events to read EEG data from
        rel_start
            Relative start times in ms
        rel_stop
            Relative stop times in ms

        Returns
        -------
        A time series with shape (channels, epochs, time). By default, this
        returns data as it was physically recorded (e.g., if recorded with a
        common reference, each channel will be a contact's reading referenced
        to the common reference, a.k.a. "monopolar channels").

        Raises
        ------
        RereferencingNotPossibleError
            When rereferencing is not possible.

        """
        eegs = []

        # sanity check on the offsets

        if rel_start != 0 and rel_stop != -1 and rel_start > rel_stop:
            raise ValueError('rel_start must precede rel_stop')

        for filename in events["eegfile"].unique():
            # select subset of events for this basename
            ev = events[events["eegfile"] == filename]

            # determine experiment, session, dtype, and sample rate
            experiment = ev["experiment"].unique()[0]
            session = ev["session"].unique()[0]
            basename = os.path.basename(filename)
            finder = PathFinder(subject=self.subject,
                                experiment=experiment,
                                session=session,
                                eeg_basename=basename,
                                rootdir=self.rootdir)
            sources = EEGMetaReader.fromfile(finder.find("sources"),
                                             subject=self.subject)
            sample_rate = sources["sample_rate"]
            dtype = sources["data_format"]
            is_scalp = dtype in (".bdf", ".raw", ".mff")

            # Convert events to epochs (onset & offset times)
            if rel_start == 0 and rel_stop == -1 and len(events) == 1:
                epochs = [(0, None)]
            else:
                epochs = convert.events_to_epochs(ev, rel_start, rel_stop,
                                                  sample_rate)

            # Scalp EEG reader requires onsets, rel_start (in sec), and rel_
            # stop (in sec) to cut data into epochs
            if is_scalp:
                on_off_epochs = epochs  # The onset & offset times will still
                # be passed to the EEGContainer later
                if rel_start == 0 and rel_stop == -1 and len(events) == 1:
                    epochs = None
                else:
                    epochs = np.zeros((len(ev), 3), dtype=int)
                    epochs[:, 0] = ev["eegoffset"]
                    epochs = dict(epochs=epochs, tmin=rel_start / 1000.,
                                  tmax=rel_stop / 1000.)

            root = get_root_dir(self.rootdir)
            eeg_filename = os.path.join(root, filename.lstrip("/"))
            reader_class = self._get_reader_class(filename)
            reader = reader_class(filename=eeg_filename,
                                  dtype=dtype,
                                  epochs=epochs,
                                  scheme=self.scheme,
                                  clean=self.clean)
            # if scalp EEG, info is an MNE Info object; if iEEG, info is a list
            # of contacts
            data, info = reader.read()

            attrs = {}
            if is_scalp:
                # Pass MNE info and events as extra attributes, to be able to
                # fully reconstruct MNE Raw/Epochs objects
                attrs["mne_info"] = info
                channels = info["ch_names"]
                if epochs is not None:
                    # Crop out any events/epoch times that ran beyond the
                    # bounds of the EEG recording
                    te_pre = info["truncated_events_pre"] \
                        if info["truncated_events_pre"] > 0 else None
                    te_post = -info["truncated_events_post"] \
                        if info["truncated_events_post"] > 0 else None
                    on_off_epochs = on_off_epochs[te_pre:te_post]
                    ev = ev[te_pre:te_post]
                # Pass the onset & offset time epoch list to EEGContainer, NOT
                # the MNE-formatted epoch list
                epochs = on_off_epochs
            elif self.scheme is not None:
                data, channels = reader.rereference(data, info)
            else:
                channels = ["CH{}".format(n + 1) for n in range(data.shape[1])]

            eegs.append(
                EEGContainer(
                    data,
                    sample_rate,
                    epochs=epochs,
                    events=ev,
                    channels=channels,
                    tstart=rel_start,
                    attrs=attrs
                )
            )

        eegs = EEGContainer.concatenate(eegs)
        eegs.attrs["rereferencing_possible"] = reader.rereferencing_possible
        return eegs
コード例 #10
0
 def test_make_time_array_samplerate(self, samplerate):
     data = np.random.random((1, 1, 100))
     ts = EEGContainer(data, samplerate=samplerate)
     assert len(ts.time) == ts.data.shape[-1]
     assert_equal(ts.time[1] - ts.time[0], 1000. / samplerate)
コード例 #11
0
    def test_make_time_array_tstart(self, tstart):
        data = np.random.random((1, 32, 2))
        rate = 1000

        ts = EEGContainer(data, rate, tstart=tstart)
        assert_equal([tstart, tstart + 1], ts.time)
コード例 #12
0
    def as_timeseries(self, events: pd.DataFrame, rel_start: Union[float, int],
                      rel_stop: Union[float, int]) -> EEGContainer:
        """Read the timeseries.

        Parameters
        ----------
        events
            Events to read EEG data from
        rel_start
            Relative start times in ms
        rel_stop
            Relative stop times in ms

        Returns
        -------
        A time series with shape (channels, epochs, time). By default, this
        returns data as it was physically recorded (e.g., if recorded with a
        common reference, each channel will be a contact's reading referenced to
        the common reference, a.k.a. "monopolar channels").

        Raises
        ------
        RereferencingNotPossibleError
            When rereferencing is not possible.

        """
        eegs = []

        for filename in events["eegfile"].unique():
            # select subset of events for this basename
            ev = events[events["eegfile"] == filename]

            # determine experiment, session, dtype, and sample rate
            experiment = ev["experiment"].unique()[0]
            session = ev["session"].unique()[0]
            finder = PathFinder(subject=self.subject,
                                experiment=experiment,
                                session=session,
                                rootdir=self.rootdir)
            sources = EEGMetaReader.fromfile(finder.find("sources"),
                                             subject=self.subject)
            sample_rate = sources["sample_rate"]
            dtype = sources["data_format"]

            # convert events to epochs
            if rel_stop < 0:
                # We're trying to load to the end of the session. Only allow
                # this in cases where we're trying to load a whole session.
                if len(events) > 1:
                    raise ValueError("rel_stop must not be negative")
                epochs = [(0, None)]
            else:
                epochs = convert.events_to_epochs(ev, rel_start, rel_stop,
                                                  sample_rate)

            root = get_root_dir(self.rootdir)
            eeg_filename = os.path.join(root, filename.lstrip("/"))
            reader_class = self._get_reader_class(filename)
            reader = reader_class(filename=eeg_filename,
                                  dtype=dtype,
                                  epochs=epochs,
                                  scheme=self.scheme)
            data, contacts = reader.read()

            if self.scheme is not None:
                data, labels = reader.rereference(data, contacts)
                channels = labels
            else:
                channels = ["CH{}".format(n + 1) for n in range(data.shape[1])]

            eegs.append(
                EEGContainer(
                    data,
                    sample_rate,
                    epochs=epochs,
                    events=ev,
                    channels=channels,
                    tstart=rel_start,
                ))

        eegs = EEGContainer.concatenate(eegs)
        eegs.attrs["rereferencing_possible"] = reader.rereferencing_possible
        return eegs