Esempio n. 1
0
    def __init__(self, app_config):
        self.config = app_config
        self.hypnodensity = list()
        self.flatline = []
        self.features = HypnodensityFeatures(app_config)
        self.edf: pyedflib.EdfFileReader = []
        '''
        encoded_data is a 1640 x N array (np.array)
        Rows represent stacked cross correlation values.
        The order is: Central, Occipital, EOG-L, EOG-R, EOG-L/R, and then chin
        The size of the cross correlation value is specied by app_config.cc_ssize, with a default of
        2s (central), 2s (occipital), 4s, 4s, 4s (eog's), and 0.4s (chin).
        Each column, represents a 0.250 s lapse or shift in time from the start of the psg (i.e. t0 = 0.0s)
        Because the psg channels are resampled to 100 Hz, the PSG channels can be sliced as follows:
         Central - 0:199
         Occipital - 200:399
         EOG-L - 400:799
         EOG-R - 800:1199
         EOG-L/R - 1200:1599
         Chin - 1600:1639
        N can be determined as follows:
        N = (D-(max(cc_size)-delta_lapse))/delta_lapse
            where D is the maximum duration of the PSG in seconds which can be divided by 30 without giving a remainder,
            max(cc_size) is 4 s, and delta_lapse is 0.25s.
        N = (D-3.75)*4
        Thus if a PSG is 30980s, then D = 30960 and N = 123825
        '''
        self.encoded_data = []
        self._encoded_data_channel_slices = {
            'central': range(0, 200),
            'occipital': range(200, 400),
            'eog-l': range(400, 800),
            'eog-r': range(800, 1200),
            'eog-lr': range(1200, 1600),
            'chin': range(1600, 1640)
        }

        self._encoded_data_channel_offsets = {
            'central': 0,
            'occipital': 200,
            'eog-l': 400,
            'eog-r': 800,
            'eog-lr': 1200,
            'chin': 1600
        }

        self.fs = int(app_config.fs)

        # Filter specifications for resampling from MATLAB
        try:
            filter_specs_path = resource_filename('_resources',
                                                  'filter_specs.json')
            with open(filter_specs_path, "r") as json_file:
                self.filter_specs = json.load(json_file)
        except FileNotFoundError:
            self.filter_specs = {}
            myprint(
                'Unable to load filter specifications file.  Default resampling filter coefficients will be used'
                ' instead.')
 def resampling(self, c, fs):
     # ratio = np.float(self.fs)/np.round(np.float(fs));
     myprint("original samplerate = ", fs);
     myprint("resampling to ", self.fs)
     numerator = [-0.0175636017706537, -0.0208207236911009, -0.0186368912579407, 0, 0.0376532652007562,
               0.0894912177899215, 0.143586518157187, 0.184663795586300, 0.200000000000000, 0.184663795586300,
               0.143586518157187, 0.0894912177899215, 0.0376532652007562, 0, -0.0186368912579407,
               -0.0208207236911009, -0.0175636017706537]  # taken from matlab
     s = signal.dlti(numerator, [1], dt=1./self.fs)
     self.loaded_channels[c] = signal.decimate(self.loaded_channels[c], int(int(fs)/self.fs), ftype=s, zero_phase=False)
Esempio n. 3
0
    def filtering(self):
        myprint('Filtering remaining signals')
        fs = self.fs

        Fh = signal.butter(5, self.fsH / (fs / 2), btype='highpass', output='ba')
        Fl = signal.butter(5, self.fsL / (fs / 2), btype='lowpass', output='ba')

        for ch in self.loaded_channels:
                myprint('Filtering {}'.format(ch))
                self.loaded_channels[ch] = signal.filtfilt(Fh[0], Fh[1], self.loaded_channels[ch])

                if fs > (2 * self.fsL):
                    self.loaded_channels[ch] = signal.filtfilt(Fl[0], Fl[1], self.loaded_channels[ch]).astype(
                        dtype=np.float32)
Esempio n. 4
0
    def filtering(self):
        myprint('Filtering remaining signals')
        fs = self.fs

        Fh = signal.butter(5, self.fsH / (fs / 2), btype='highpass', output='ba')
        Fl = signal.butter(5, self.fsL / (fs / 2), btype='lowpass', output='ba')

        for ch, ch_idx in self.channels_used.items():
            # Fix for issue 9: https://github.com/Stanford-STAGES/stanford-stages/issues/9
            if isinstance(ch_idx, int):
                myprint('Filtering {}'.format(ch))
                self.loaded_channels[ch] = signal.filtfilt(Fh[0], Fh[1], self.loaded_channels[ch])

                if fs > (2 * self.fsL):
                    self.loaded_channels[ch] = signal.filtfilt(Fl[0], Fl[1], self.loaded_channels[ch]).astype(
                        dtype=np.float32)
 def resampling(self, ch, fs):
     myprint("original samplerate = ", fs);
     myprint("resampling to ", self.fs)
     if fs==500 or fs==200:
         numerator = [[-0.0175636017706537, -0.0208207236911009, -0.0186368912579407, 0.0, 0.0376532652007562,
             0.0894912177899215, 0.143586518157187, 0.184663795586300, 0.200000000000000, 0.184663795586300,
             0.143586518157187, 0.0894912177899215, 0.0376532652007562, 0.0, -0.0186368912579407,
             -0.0208207236911009, -0.0175636017706537],
             [-0.050624178425469, 0.0, 0.295059334702992, 0.500000000000000, 0.295059334702992, 0.0,
             -0.050624178425469]]  # from matlab
         if fs==500:
             s = signal.dlti(numerator[0], [1], dt=1. / self.fs)
             self.loaded_channels[ch] = signal.decimate(self.loaded_channels[ch], fs // self.fs, ftype=s, zero_phase=False)
         elif fs==200:
             s = signal.dlti(numerator[1], [1], dt=1. / self.fs)
             self.loaded_channels[ch] = signal.decimate(self.loaded_channels[ch], fs // self.fs, ftype=s, zero_phase=False)
     else:
         self.loaded_channels[ch] = signal.resample_poly(self.loaded_channels[ch],
                                     self.fs, fs, axis=0, window=('kaiser', 5.0))
    def loadEDF(self):
        if not self.edf:

            try:
                self.edf = pyedflib.EdfReader(self.edf_pathname)
            except OSError as osErr:
                print("OSError:", "Loading", self.edf_pathname)
                raise (osErr)

        for ch in self.channels:  # ['C3','C4','O1','O2','EOG-L','EOG-R','EMG','A1','A2']
            myprint('Loading', ch)
            if isinstance(self.channels_used[ch], int):

                self.loaded_channels[ch] = self.edf.readSignal(self.channels_used[ch])
                if self.edf.getPhysicalDimension(self.channels_used[ch]).lower() == 'mv':
                    myprint('mv')
                    self.loaded_channels[ch] *= 1e3
                elif self.edf.getPhysicalDimension(self.channels_used[ch]).lower() == 'v':
                    myprint('v')
                    self.loaded_channels[ch] *= 1e6

                fs = int(self.edf.samplefrequency(self.channels_used[ch]))
                # fs = Decimal(fs).quantize(Decimal('.0001'), rounding=ROUND_DOWN)
                print('fs', fs)

                self.resampling(ch, fs)
                print('Resampling done')

                # Trim excess
                self.trim(ch)

            else:
                print('channel[', ch, '] was empty (skipped)', sep='')
                del self.channels_used[ch]
Esempio n. 7
0
 def myprint(self, string, *args):
     if self.config.verbose:
         myprint(string, *args)
    def evaluate(self):
        p = Path(self.edf_pathname)
        p = Path(p.with_suffix('.pkl'))

        h = Path(self.edf_pathname)
        h = Path(h.with_suffix('.hypno_pkl'))

        if (p.exists()):

            myprint('Loading previously saved encoded data')
            with p.open('rb') as fp:
                self.encodedD = pickle.load(fp)
        else:
            myprint('Load EDF')
            self.loadEDF()
            # myprint('Load noise level')
            # self.psg_noise_level()
            print('Encode')
            self.encoding()

            # pickle our file
            with p.open('wb') as fp:
                pickle.dump(self.encodedD, fp)
                myprint("pickling done")

        if (h.exists()):
            myprint('Loading previously saved hynpodesnity')
            with h.open('rb') as fp:
                self.hypnodensity = pickle.load(fp)
        else:
            myprint('Score data')
            self.score_data()
            # pickle our file
            with h.open('wb') as fp:
                pickle.dump(self.hypnodensity, fp)
                myprint("Hypnodensity pickled")
    def encoding(self):

        count = -1
        enc = []
        # Central, Occipital, EOG and chin

        numIterations = 4;  # there are actually 5 for CC, but this is just for displaying progress
        numConcatenates = 5;
        for c in self.channels:  # ['C3','C4','O1','O2','EOG-L','EOG-R','EMG','A1','A2']
            start_time = time.time()

            if isinstance(self.channels_used[c], int):
                count += 1
                n = int(self.fs * self.CCsize[c])
                p = int(self.fs * (self.CCsize[c] - 0.25))

                # TODO: There is an error in this buffer somewhere // Alex
                B1 = self.buffering(self.loaded_channels[c], n, p)
                print(B1.shape)
                zeroP = np.zeros([int(B1.shape[0] / 2), B1.shape[1]])
                B1 = np.concatenate([zeroP, B1, zeroP], axis=0)

                n = int(self.fs * self.CCsize[c] * 2)
                p = int(self.fs * (self.CCsize[c] * 2 - 0.25))

                B2 = self.buffering(np.concatenate([np.zeros(int(n / 4)),
                                                    self.loaded_channels[c], np.zeros(int(n / 4))]), n, p)

                B2 = B2[:, :B1.shape[1]]

                start_time = time.time()

                F = np.fft.fft(B1, axis=0)
                C = np.conj(np.fft.fft(B2, axis=0))

                elapsed_time = time.time() - start_time
                myprint("Finished FFT  %d of %d\nTime elapsed = %0.2f" % (count + 1, len(self.channels), elapsed_time));
                start_time = time.time()

                CC = np.real(np.fft.fftshift(np.fft.ifft(np.multiply(F, C), axis=0), axes=0))

                elapsed_time = time.time() - start_time
                myprint("Finished CC 1 %d of %d\nTime elapsed = %0.2f" % (count + 1, len(self.channels), elapsed_time));
                start_time = time.time()

                CC[np.isnan(CC)] = 0
                CC[np.isinf(CC)] = 0

                CC = CC[int(CC.shape[0] / 4):int(CC.shape[0] * 3 / 4), :]
                sc = np.max(CC, axis=0)
                sc = np.multiply(np.sign(sc), np.log((np.abs(sc) + 1) /
                                                     (self.CCsize[c] * self.fs))) / (sc + 1e-10)

                CC = np.multiply(CC, sc)
                CC.astype(np.float32)

                if len(enc) > 0:
                    enc = np.concatenate([enc, CC])
                else:
                    enc = CC

                if count == 2:
                    eog1 = F

                if count == 3:
                    PS = eog1 * C
                    CC = np.real(np.fft.fftshift(np.fft.ifft(PS, axis=0), axes=0))
                    CC = CC[int(CC.shape[0] / 4):int(CC.shape[0] * 3 / 4), :]
                    sc = np.max(CC, axis=0)
                    sc = np.multiply(np.sign(sc), np.log((np.abs(sc) + 1) /
                                                         (self.CCsize[c] * self.fs))) / (sc + 1e-10)

                    CC = np.multiply(CC, sc)
                    CC.astype(np.float32)

                    enc = np.concatenate([enc, CC])

                # pdb.set_trace()
                elapsed_time = time.time() - start_time
                myprint("Finished enc concatenate %d of %d\nTime elapsed = %0.2f" % (
                count + 1, len(self.channels), elapsed_time))

        self.encodedD = enc

        if isinstance(self.lightsOff, int):
            self.encodedD = self.encodedD[:, 4 * 30 * self.lightsOff:4 * 30 * self.lightsOn]