def sigcontainer(self) -> SigContainer: fs, data = self.read() if list(data.keys()) == [0]: data = np.array(data[0]).reshape((1, len(data[0]))) channel = self.channels if self.channels[0] else self.shortpath.stem container = SigContainer.from_signal_array(data, channels=[channel], units=["mV"], fs=self.fs) else: # multichannel data = np.vstack( tuple( np.array(data[chan]).reshape(1, len(data[chan])) for chan in sorted(data.keys()))) if self.channels is None: labels = [ f"{self.shortpath.stem}: channel {chan}" for chan in sorted(self.data.keys()) ] else: labels = [ f"{self.shortpath.stem}: {self.channels[chan]}" for chan in sorted(self.data.keys()) ] container = SigContainer.from_signal_array( data, channels=labels, units=["mV"] * len(labels), fs=fs, basepath=str(self.shortpath)) return container
def apply(self, container: SigContainer) -> Any: data = container.d[self.target + "/data"] channels = container.d[self.target + "/channels"] container = self.prepare_container(container) container.d["signals/data"] = data container.d["signals/channels"] = channels return container
def join(self, output: SigContainer, inputs: Sequence[SigContainer]) -> SigContainer: result = np.copy(output.signals) for inc in inputs: self.ufunc(result, inc.signals, out=result) output.d["signals/data"] = result output.d["signals/channels"] = [ f"{self.ufunc.__name__}({', '.join(input.d['signals/channels'][i] for input in [output] + list(inputs))})" for i in range(output.channel_count)] return output
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) oldlength = container.sample_count container.d["signals/data"] = sig.resample( container.d["signals/data"].transpose(), self.nlen).transpose() if self.chfreq: container.d["signals/fs"] = self.nlen * container.d[ "signals/fs"] / oldlength #FIXME: change annotation position return container
def join(self, output: SigContainer, inputs: Sequence[SigContainer]) -> SigContainer: if self.names is not None: output.d["signals/channels"] = self.names for input in inputs: output.d["signals/data"] = np.hstack((output.signals, input.signals)) if self.names is None: output.d["signals/channels"] = [ output.d["signals/channels"][i] + " + " + input.d["signals/channels"][i] for i in range(len(output.d["signals/channels"]))] return output
def join(self, output: SigContainer, inputs: Sequence[SigContainer]) -> SigContainer: assert len(inputs) <= 1, "Convolution with more than two signal is not supported" in1 = output in2 = inputs[0] if inputs else in1 result = np.vstack([ convolve(in1.signals[i, :], in2.signals[i, :], self.mode, self.method) for i in range(in1.signals.shape[0]) ]) output.d["signals/data"] = result output.d["signals/lag"] = output.sample_count // 2 return output
def apply(self, container: SigContainer) -> Any: dmax = np.max(container.signals, axis=1).reshape(container.channel_count, 1) dmin = np.min(container.signals, axis=1).reshape(container.channel_count, 1) drange = (dmax - dmin).reshape(container.channel_count, 1) range = self.max - self.min container.d["signals/data"] = self.min + range * (container.signals - dmin) / drange container.d["signals/units"] = ["unit"] * container.channel_count return container
def container_factory(self, container: SigContainer, a: int, b: int, splitter_id: str) -> SigContainer: c = SigContainer( container.d.deepcopy(empty_folders=["meta", "annotations"])) c.d["signals/data"] = c.d["signals/data"][:, a:b] newlog = list(c.d["log"]) newlog.append(f"{splitter_id}@{a}-{b}") c.d["log"] = newlog if "annotations" in container.d: c.d["annotations"].update( SigContainer.cut_annots(container.d["annotations"], a, b)) return c
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) assert container.channel_count == 1, "only one channel signal is supported" emd = EMD() IMFs = emd(container.signals[0,:]) oname = container.d["signals/channels"][0] if self.include: container.d["signals/data"] = np.vstack((container.signals, IMFs)) container.d["signals/channels"] = [oname] + [f"{oname} IMF_{i+1}" for i in range(IMFs.shape[0])] container.d["signals/units"] *= IMFs.shape[0] + 1 else: container.d["signals/data"] = IMFs container.d["signals/channels"] = [f"{oname} IMF_{i+1}" for i in range(IMFs.shape[0])] container.d["signals/units"] *= IMFs.shape[0] return container
def sigcontainer(self) -> SigContainer: """ Returns ------- SigContainer Generated waveform in a SigContainer type. """ if self.channel_name is None: self.channel_name = [ self.sig_type.value + '(f=' + str(self.sig_frequency) + ', φ=' + str(self.sig_phase) + 'π, A=' + str(self.sig_amplitude) ] if self.amplitude_units is None: self.amplitude_units = [''] x = np.linspace(0, self.sig_duration, int(self.fs * self.sig_duration)).reshape( 1, int(self.fs * self.sig_duration)) sig_base = self.__sig_switch(self.sig_type, self.sig_frequency, self.sig_amplitude, self.sig_phase, x) generated_sig = SigContainer.from_signal_array(sig_base, self.channel_name, self.amplitude_units, float(self.fs), basepath=self.filepath) return generated_sig
def sigcontainer(self) -> SigContainer: """ Returns ------- SigContainer Generated noise in a SigContainer type. """ noise = self.__noise_switch(self.noise_type, self.st_deviation, self.noise_duration, self.fs) \ .reshape(1, int(self.fs * self.noise_duration)) for _ in range(self.channels - 1): noise = np.vstack([ noise, self.__noise_switch(self.noise_type, self.st_deviation, self.noise_duration, self.fs) ]) if self.channel_names is None: self.channel_names = [ f"{self.noise_type.value} noise (σ={self.st_deviation})" ] * self.channels if self.amplitude_units is None: self.amplitude_units = [' '] * self.channels generated_noise = SigContainer.from_signal_array( noise, self.channel_names, self.amplitude_units, float(self.fs), basepath=self.filepath) return generated_noise
def join(self, outcontainer: SigContainer, incontainers: Sequence[SigContainer]) -> SigContainer: result = np.copy(outcontainer.signals) for inc in incontainers: result += inc.signals outcontainer.d["signals/data"] = result return outcontainer
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) fs = container.d["signals/fs"] sos = self.cg(fs) container.d["signals/data"] = sig.sosfilt(sos, container.d["signals/data"], **self.params) return container
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) result = np.empty_like(container.d["signals/data"]) for i in range(container.channel_count): result[i] = sig.medfilt(container.d["signals/data"][i, :], self.window_length) container.d["signals/data"] = result return container
def simpledata(): sig = np.array([[0, 1, 0, -1, 0, 1, 0, -1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1]]) c = SigContainer.from_signal_array(signals=sig, channels=["saw", "ones"], units=["mV", "mV"], fs=1) return c
def sigcontainer(self) -> SigContainer: return SigContainer.from_csv(self._filepath, dialect=self.dialect, header=self.header, default_unit=self.default_unit, fs=self.fs, transpose=self.transpose, annotation=self.annotation)
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) fs = container.d["signals/fs"] lag = container.lag start = TimeUnit.to_sample(self.start, fs, TimeUnit.time_unit_mapper(self.start), lag) end = TimeUnit.to_sample(self.end, fs, TimeUnit.time_unit_mapper(self.end), lag) container.d["signals/data"] = container.d["signals/data"][:, start:end] container.d["signals/lag"] = lag - start if "annotations" in container.d: adict = container.d["annotations"] newdict = SigContainer.cut_annots(adict, start, end) adict.update(newdict) return container
def sigcontainer(self) -> SigContainer: data = np.full((self.channels, int(self.duration * self.fs)), self.value, dtype=np.float64) if self.channel_names is None: self.channel_names = [f"constant:{self.value}"] * self.channels if self.units is None: self.units = [''] * self.channels return SigContainer.from_signal_array(data, self.channel_names, self.units, self.fs, basepath=self.filepath)
def join(self, output: SigContainer, inputs: Sequence[SigContainer]) -> SigContainer: for input in inputs: output.d["signals/data"] = np.vstack( (output.signals, input.signals)) output.d["signals/channels"].extend(input.d["signals/channels"]) output.d["signals/units"].extend(input.d["signals/units"]) return output
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) result = np.empty_like(container.d["signals/data"]) for i in range(container.channel_count): result[i] = np.correlate(container.d["signals/data"][i, :], self.v, mode="same") / self.sum container.d["signals/data"] = result return container
def sigcontainer(self) -> SigContainer: container = SigContainer.from_signal_array(self.data.transpose(), channels=self.channels, units=self.units, fs=self.fs) for annotator in self.annotations.keys(): samples = self.annotations[annotator]["sample"] symbols = [self.annotations[annotator]["symbol"]] * len(samples) notes = "" * len(samples) container.add_annotation(annotator, samples, types=symbols, notes=notes) return container
def apply(self, container: SigContainer) -> SigContainer: container = self.prepare_container(container) if self.new_freq is not None: f = fractions.Fraction( self.new_freq / container.d["signals/fs"]).limit_denominator(100) self.up = f.numerator self.down = f.denominator container.d["signals/data"] = sig.resample_poly( container.d["signals/data"], self.up, self.down, axis=1) container.d[ "signals/fs"] = self.up * container.d["signals/fs"] / self.down if "annotations" in container.d: andict = container.d["annotations"] for ann in andict.keys(): andict[ann]["samples"] = [ self.up * sample // self.down for sample in andict[ann]["samples"] ] return container
def apply(self, container: SigContainer) -> Union[SigContainer, pd.DataFrame]: df = pd.DataFrame(data=container.d["signals/data"].transpose(), columns=container.d["signals/channels"], index=container.x_index(self.time_unit, container.d["signals/fs"])) if self.to_file is None: return df else: file = self.to_file.format(container) df.to_pickle(file) return container
def apply(self, container: SigContainer) -> Sequence[SigContainer]: container = self.prepare_container(container) limits = container.get_annotation_positions(self.aspec, TimeUnit.SAMPLE, container.d["signals/fs"]) if self.left_segment and limits[0] != 0: limits = np.insert(limits, 0, 0) if self.right_segment and limits[-1] != container.sample_count - 1: limits = np.append(limits, [container.sample_count]) return [ self.container_factory(container, a, b, f"MSPL@{self.aspec}]") for a, b in zip(limits, limits[1:]) ]
def apply(self, container: SigContainer) -> SigContainer: import csv container = self.prepare_container(container) path = self.filepath.base_path( container.basepath.extend_stem(container.id).resuffix(".csv")) x = container.x_index(self.time_unit, container.d["signals/fs"]) opener = open if not self.gzipped else gzip.open with opener(str(path), "wt", newline='') as csvfile: writer = csv.writer(csvfile, dialect=self.dialect) writer.writerow(["time"] + container.d["signals/channels"]) for i in range(container.signals.shape[1]): writer.writerow([ f"{val:g}" for val in np.hstack((x[i], container.signals[:, i])) ]) return container
def apply(self, container: SigContainer) -> Sequence[SigContainer]: container = self.prepare_container(container) containers = [] #TODO: zohlednit kanály for i in range(container.channel_count): c = SigContainer( container.d.deepcopy(["annotations"], empty_folders=["signals", "meta"])) c.d["signals/data"] = container.d["signals/data"][i, :].reshape( 1, container.sample_count) c.d["signals/channels"] = [container.d["signals/channels"][i]] c.d["signals/units"] = [container.d["signals/units"][i]] c.d["signals/fs"] = container.d["signals/fs"] c.d["log"] = list(container.d["log"]) c.d["log"].append(f"C{i}") containers.append(c) return containers
def sigcontainer(self, annotators: Iterable[str] = None) -> SigContainer: c = SigContainer.from_signal_array(signals=np.transpose(self.record.p_signal), channels=self.record.sig_name, units=self.record.units, fs=self.record.fs) if annotators is not None: with h5py.File("physionet_cache.h5") as store: for annotator in annotators: if annotator not in self.annotations: annopath = f"{self.path}/{annotator}" if annopath not in store: self.annotations[annotator] = wfdb.rdann(self.name, annotator, pb_dir=self.database) store.create_dataset(annopath, data=dumpa(self.annotations[annotator]), compression="gzip") else: self.annotations[annotator] = pickle.loads(store[annopath][:]) data = self.annotations[annotator] c.add_annotation(annotator, data.sample, data.symbol, data.aux_note) return c
def test_hdf5_roundtrip(megawindata): original = megawindata | Hdf5("/tmp/test.h5") serialized = SigContainer.from_hdf5("/tmp/test.h5") assert np.all(original.signals == serialized.signals)
def apply(self, container: SigContainer) -> Any: container = self.prepare_container(container) h = sig.hilbert(container.signals, axis=1) container.d["signals/data"] = np.sqrt(np.real(h)**2 + np.imag(h)**2) return container
def prepare_container(self, container: SigContainer) -> SigContainer: return SigContainer(container.d.deepcopy(shared_folders=["annotations"], empty_folders=["meta"]))