def test_save_complex_data(self): meta = {} with open("data/log_files/meta_log_V_0-0_1_1464.log", "r") as meta_file: for line in meta_file.readlines(): spli = line.split(",") meta[spli[0]] = spli[1].rstrip("\n") with open("data/log_files/save_file_V_0-0_1_1464.log", "r") as save_file: file_content = save_file.read() sample = file_content.split(",") sample = list(map(float, sample)) reshaped_sig = np.array(sample).reshape((-1, 1)) max_min = max(np.max(reshaped_sig), abs(np.min(reshaped_sig))) reshaped_sig = reshaped_sig / max_min wfdb.wrsamp("V_0-0_1_1464", fs=500, units=["mV"], p_signal=reshaped_sig, comments=[], base_date=None, base_time=None, fmt=["32"], sig_name=['ECG1'], write_dir="data/failed_writes")
def get_record_signal(self, path=''): # record = wfdb.Record(recordname='Test'+str(i),fs=300,nsig=1,siglen=750,p_signals=x, # filename=['test.dat'],baseline=[50],units=['mV'],signame=['ECG'],adcgain=[200],fmt=['16'],checksum=[0], # adcres=[16],adczero=[0],initvalue=[0],blocksize=[0], d_signals=None) #array_signal = np.concatenate((array_signal,SignalRetriever.sample_signal(inter_func,points))) inter_fun, x, y, skew = SignalRetriever.retrieve_signal( self.coordinates_file) sampled_signal = SignalRetriever.sample_signal(inter_fun, x) #sampled_signal = wp.normalize(sampled_signal,-1,1) name = self.file_name.split('/') wfdb.wrsamp(name[-1][:-4], 300, ['mV'], ['ALL_LEADS'], sampled_signal, None, ['32'], [1000], [0]) ''' record = wfdb.Record( recordname = name, fs = 300, nsig = 1, siglen = len(sampled_signal), filename = [path+name], units = 'mV', signame = ['ECG ALL LEADS'], adcgain=[1000], baseline = [0], fmt=['16'], checksum=[0], d_signals= sampled_signal ) ''' return
def test_save_annotation(self): wfdb.wrann("test_record_save_ann", 'atr', np.array([1]), np.array(["N"]), fs=360, write_dir="data/ann") a = [1, 2, 4, 4, 5, 6, 7, 8, 1, 5, 3, 5, 6, 6] a = list(map(lambda x: list([x]), a)) wfdb.wrsamp("test_record_save_ann", 360, ["mV"], ["I"], np.array(a, np.float64), comments=None, base_date=None, base_time=None, write_dir="data/ann") wfdb.rdann("data/ann/test_record_save_ann_fs", "atr")
def store_as_wfdb(signame, data, sigfolder, fs): channel_itos=['I', 'II', 'III', 'AVR', 'AVL', 'AVF', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6'] wfdb.wrsamp(signame, fs=fs, sig_name=channel_itos, p_signal=data, units=['mV']*len(channel_itos), fmt = ['16']*len(channel_itos), write_dir=sigfolder)
def test_save_read_sample(self): record_name = self.mitdb + '100' sig, fields = wfdb.rdsamp(record_name, channels=[0]) print(sig) sig = list(map(lambda x: list(x), list(sig))) sig = np.array(sig) wfdb.wrsamp('m_100', fields['fs'], fields['units'], fields['sig_name'], sig, comments=fields['comments'], base_date=fields['base_date'], base_time=fields['base_time'], write_dir='data/samples/')
def write_to(self, record_name: str, dir_path: str, *, fmt: str = "32") -> None: """ Params: record_name: name of record (i.e. of header and data file) dir_path: name of target directory fmt: physionet data format for digital signals (verified formats: 16, 32) """ import wfdb wfdb.wrsamp(record_name, fs=self.fs, units=self.units, p_signal=self.data, sig_name=self.channels, write_dir=dir_path, fmt=[fmt] * self.data.shape[1]) for annotator in self.annotations.keys(): sample = self.annotations[annotator]["sample"] symbols = [self.annotations[annotator]["symbol"]] * len(sample) wfdb.wrann(record_name, annotator, sample, symbol=symbols, write_dir=dir_path)
def save_typed_datasets(self, symbol, datasets): for idx, samples in enumerate(datasets): anno = self.test_annotations[symbol][idx] meta = self.test_fields[symbol][idx] self.last_written_idx.setdefault(symbol, 0) corrected_idx = self.last_written_idx[symbol] + idx record_name = "{}_{}".format(symbol.replace(".", "-"), corrected_idx) try: reshaped_data = np.reshape(samples, (-1, 1)).astype(np.float64) max_min = max(np.max(reshaped_data), abs(np.min(reshaped_data))) if max_min != 0: reshaped_data = reshaped_data / max_min np.nan_to_num(reshaped_data) sig_names = [sn.replace(" ", "") for sn in meta['sig_name']] wfdb.wrsamp(record_name, self.__target_frequency__, meta['units'], sig_names, p_signal=reshaped_data, fmt=["32"], comments=meta['comments'], base_date=meta['base_date'], base_time=meta['base_time'], write_dir=os.path.join(self.data_folder_path, symbol)) wfdb.wrann(record_name, 'atr', np.array(anno), np.array([symbol[0]] * len(anno)), fs=self.__target_frequency__, write_dir=os.path.join(self.ann_data_path)) with open( os.path.join(self.data_folder_path, symbol, "RECORDS"), 'a') as records_file: records_file.writelines([record_name + "\n"]) except ValueError as v: print("Failed to write", record_name, "because", str(v)) self.clean_up_wrong_writes(symbol, record_name) print(symbol[0], int(symbol.split("_")[-1])) self.collected_data[symbol[0]][int(symbol.split("_")[-1])] -= 1 self.failed_writes.setdefault(symbol, 0) self.failed_writes[symbol] += 1 self.last_written_idx[symbol] += len(datasets)
def ResampleRecordFile(record_source_dir, record_source_name, record_target_dir, record_target_name, target_frequency): ''' Creates a new record file with a new frequency. Uses wfdb functions :param record_source_name: path to source record (no extension) :param record_target_name: path to target record (no extension) :param target_frequency: in Hz :return: ''' # Read part of a record from Physiobank record_source_path = record_source_dir + '\\' + record_source_name signals, fields = wfdb.rdsamp(record_source_path) print('Record to resample', record_source_path) print(fields) print('Original signal shape', np.shape(signals)) # see docs: https://wfdb.readthedocs.io/en/latest/processing.html#wfdb.processing.resample_sig signals = np.transpose( signals) # transpose, so that to following loop works resampled_signals = [ wfdb.processing.resample_sig(signal, fields['fs'], target_frequency)[0] for signal in signals ] resampled_signals = np.transpose( resampled_signals) # transpose back, so wfdb.wrsamp() works print('resampled signal shape', np.shape(resampled_signals)) # Write a local WFDB record units = fields['units'] signal_names = [name.replace(" ", "_") for name in fields['sig_name'] ] # replace possible whitespaces fmt = ['16'] * len( units ) # fmt: I don't know what this does exactly, and what to configure... wfdb.wrsamp(record_name=record_target_name, write_dir=record_target_dir, fs=target_frequency, units=units, sig_name=signal_names, p_signal=resampled_signals, fmt=fmt) return
def ECG_signal2QRS(ecg, Ts, draw=False): if ~np.isnan(Ts): # ES NECESARIO Ts # RESAMPLE DE LA SEÑAL ecg = signal.resample_poly(ecg, 360, round(1 / Ts)) Ts = 1 / 360 ecg = filterSignal(ecg) tm = np.arange(0, len(ecg) * Ts, Ts)[:len(ecg)] # GENERA FILENAME RANDOM filename = 'tmp' + str(int(np.mean(ecg) * 10)) # GUARDA LA SENAL ECG EN FORMATO WFDB wfdb.wrsamp(filename, fs=1 / Ts, units=['mV'], sig_name=['I'], p_signal=ecg, fmt=['212']) # ESTIMA EL COMPLEJO QRS try: out = subprocess.Popen(['ecgpuwave', '-r', filename, '-a', 'test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = out.communicate() # LEE LA ESTIMACION DEL COMPLEJO QRS Q, T, R, anntype, ann, R_ann = readAnnotation(filename) # DIBUJA LAS ESTIMACION REALIZADA POR ECGPUWAVE if draw: plotEstimation(ecg, tm, Q, T, R) # CALCULO DEL TIEMPO QT qtc = computeQTtimes(anntype, ann, R_ann, tm) except: qtc = -1 else: qtc = -2 return qtc
def process_one_record(src_file, dest_file, config): data, fields = wfdb.rdsamp(src_file) numch = data.shape[1] hdr = { "fs": fields["fs"], "adc_gain": np.array([1.0] * numch), "baseline": np.array([0.0] * numch), "samples": data.shape[0], "channels": data.shape[1] } if config["PREPROCESSING"].get("baseline_correction", True): ubsig = fix_baseline( data, fields["fs"], config["BASELINE"]["unbias_window_ms"] ) else: ubsig = np.array(data, "float") if config["PREPROCESSING"].get("mains_correction", True): umsig = mains_filter( ubsig, fs=fields["fs"], bias=hdr["baseline"], mains=config["MAINS_FILTER"]["base_freq"], attenuation=config["MAINS_FILTER"]["attenuation"], aperture=config["MAINS_FILTER"]["fft_size"] ) else: umsig = ubsig.copy() wfdb.wrsamp( dest_file, fs=fields["fs"], units=fields["units"], sig_name=fields["sig_name"], comments=fields["comments"], p_signal=umsig, fmt=fields.get("fmt", ["16"]*umsig.shape[1]) )
def CPSC2MIT(): data_path = 'mit-bih-arrhythmia-database-1.0.0/CPSC2019/data/' ref_path = 'mit-bih-arrhythmia-database-1.0.0/CPSC2019/ref/' for i in range(2000): print("processing round:", i) index = "%05d" % (i + 1) data_name = data_path + 'data_' + index + '.mat' ref_name = ref_path + 'R_' + index + '.mat' ecg_data = scio.loadmat(data_name)['ecg'] ecg_ref_2d = scio.loadmat(ref_name)['R_peak'] ecg_ref = list() symbols = list() for i in range(len(ecg_ref_2d)): ecg_ref.append(ecg_ref_2d[i][0]) symbols.append('N') ecg_ref = np.array(ecg_ref) wfdb.wrsamp('CPSC' + index, fs=500, units=['mV'], sig_name=['I'], p_signal=ecg_data, fmt=['212']) wfdb.wrann('CPSC' + index, 'atr', ecg_ref, symbol=symbols)
def ecgpuwave_detect_sig(sig, fs, from_samp=0, to_samp=-1, **kw): """ Runs the ecgpuwave QRS detector on a single channel ECG signal, and returns the indices of detections. :param sig: A 1-d numpy array containing one ECG channel. :param fs: The sampling frequency of that channel. :param from_samp: Start sample index. :param to_samp: End sample index. -1 for end of record. :return: A numpy array of sample indices corresponding to detected features (either R-peaks or QRS onset). """ assert sig.ndim == 1 sig = sig[from_samp:to_samp].reshape(-1, 1) # We'll write the given data to a temporary record temp_dir = tempfile.gettempdir() temp_recname = f"tmprec_{os.getpid()}" rec_path = os.path.join(temp_dir, temp_recname) try: wfdb.wrsamp( record_name=temp_recname, fs=fs, units=["mV"], sig_name=["ECG"], p_signal=sig, write_dir=temp_dir, fmt=["212"], ) return ecgpuwave_detect_rec(rec_path, channel=0, **kw) finally: # Remove the temporary record for f in glob.glob(os.path.join(rec_path, ".*")): os.remove(f)
#imsave(self.dir+'/'+'img_{0}_bn.jpg'.format(i),bn_image) inter_func = SignalRetriever.retrieve_signal(points, image) x = SignalRetriever.sample_signal(inter_func, points) # record = wfdb.Record(recordname='Test'+str(i),fs=300,nsig=1,siglen=750,p_signals=x, # filename=['test.dat'],baseline=[50],units=['mV'],signame=['ECG'],adcgain=[200],fmt=['16'],checksum=[0], # adcres=[16],adczero=[0],initvalue=[0],blocksize=[0], d_signals=None) #array_signal = np.concatenate((array_signal,SignalRetriever.sample_signal(inter_func,points))) array_signal.append(x) i += 1 return array_signal if __name__ == '__main__': sr = SignalRetriever(*os.listdir('img0'), exclude=True, dir='img0') array_signal = sr.get_multisignal_from_images() # m_record = wfdb.MultiRecord(recordname='Test', segments=array_signal,nsig=len(array_signal), # siglen=9000, # fs=300, # segname=[str(i) for i in range(len(array_signal))], # seglen=[750]*len(array_signal)) wfdb.wrsamp(recordname='Test', fs=300, units=['mV'], signames=['Lead_X'], p_signals=array_signal[0], fmt=['16'], baseline=[-1], gain=[1000])
import wfdb dbName = 'wrist' recName = 's1_walk' # Read part of a record from Physiobank sig, fields = wfdb.rdsamp(dbName + '/' + recName, sampfrom=1000, channels=[0]) record = wfdb.rdrecord(dbName + '/' + recName) print(record.__dict__) # Call the gateway wrsamp function, manually inserting fields as function input parameters wfdb.wrsamp('ecg-record', fs=256, units=['mV'], sig_name=['chest_ecg'], p_signal=sig, fmt=['16']) # The new file can be read record = wfdb.rdrecord('ecg-record') wfdb.plot_wfdb(record)
def ECG_writer(signal_sqi, file_name, file_type, info = None): """ Parameters ---------- signal_sqi : SignalSQI object containing signals, sampling rate and sqi file_name : name of file to write, with extension. For edf file_type, possible extensions are edf, edf+, bdf, bdf+. For mit file_type, : possible extensions are... : file_type : edf or mit or csv info : list In case of writing edf file: A list containing signal_headers and header (in order). signal_headers is a list of dict with one signal header for each signal channel. header (dict) contain ecg file information. In case of writing wfdb record (mit file): A dict containing header as defined in .hea file. (Default value = None) Returns ------- """ signals = signal_sqi.signals sampling_rate = signal_sqi.sampling_rate start_datetime = signal_sqi.start_datetime assert isinstance(sampling_rate, int) or isinstance(sampling_rate, float), \ 'sampling rate must be either int or float' if file_type == 'edf': signals = signals.transpose() if info is not None: signal_headers = info[1] header = info[0] annotations = header['annotations'] # issue https://github.com/holgern/pyedflib/issues/119 for i in range(len(annotations)): if isinstance(header['annotations'][i][1], bytes): header['annotations'][i][1] = \ float(str(header['annotations'][i][1], 'utf-8')) highlevel.write_edf(file_name, signals, signal_headers, header, file_type = -1, digital = False, block_size = -1) else: highlevel.write_edf_quick(file_name, signals, sampling_rate) return os.path.isfile(file_name) if file_type == 'mit': if info is None: raise Exception("Header dict needed") else: wrsamp(record_name = file_name.split('/')[-1], fs = sampling_rate, units = info['units'], sig_name = info['sig_name'], p_signal = signals, base_date = info['base_date'], base_time = info['base_time'], comments = info['comments'], write_dir = '/'.join(file_name.split('/')[:-1])) return glob.glob(file_name + '.*') if file_type == 'csv': timestamps = generate_timestamp(start_datetime, sampling_rate, signals.shape[0]) signals = pd.DataFrame(np.hstack((np.array(timestamps).reshape(-1, 1), signals))) signals.to_csv(path_or_buf = file_name, index = False, header = True) return os.path.isfile(file_name)
from dtureader import dturead if __name__ == "__main__": if len(sys.argv) > 1: fn = sys.argv[1] d, fs1, n = dturead(fn) signal = d n_sig = 6 wfdb.wrsamp("name", fs=4000, units=["mV"] * n_sig, sig_name=[ "ch1otv1", "ch1otv2", "ch1otv3", "ch2ovt1", "ch2otv2", "ch2otv3" ], p_signal=signal, fmt=["16"] * n_sig, write_dir="directory") signals, fields = wfdb.rdsamp("directory\name", sampfrom=0, sampto="end", channels="all") fs = 4000 t = np.arange(0, len(signals) / fs, 1.0 / fs) plt.plot(t, signals) plt.xlim([0, 0.01]) plt.title("Signals") print("Look at the plots")
#将txt转为.dat .hea 文件, 以2.txt为例 signals = np.zeros((5000,8)) file = open('2','r') line = file.readline() i=0 while line!='': linex = line.strip().split() for j in range(0,len(linex),1): signals[i][j] = eval(linex[j]) i = i+1 line = file.readline() file.close() wfdb.wrsamp('2', fs = 500, units=['mV', 'mV', 'mV', 'mV', 'mV', 'mV', 'mV', 'mV'], sig_name=['I','II','V1','V2','V3','V4','V5','V6'], p_signal=signals, fmt=['16', '16', '16', '16', '16', '16', '16', '16']) #fs是采样频率, fmt是16进制存储 #使用gqrs定位算法矫正峰值位置 def peaks_hr(sig, peak_inds, fs, title, figsize=(20,10), saveto=None): #这个函数是用来画出信号峰值和心律 #计算心律 hrs=processing.compute_hr(sig_len=sig.shape[0], qrs_inds=peak_inds, fs=fs) N=sig.shape[0] fig, ax_left=plt.subplots(figsize=figsize) ax_right=ax_left.twinx()
sigsplit = np.hsplit( sig, count ) #дробим массив sig, в котором записаны данные всех файлов, на строки, число которых равно число файлов #print("sigsplit=") #print(sigsplit) signal = np.transpose( sigsplit ) #транспонтруем полученный ранее полученный массив (далее его и отправим в wrsamp) #print("signal=") #print(signal) wfdb.wrsamp("name", fs=2000, units=["mV"] * count, sig_name=["name1", "name2", "name3"], p_signal=signal, fmt=["16"] * count, write_dir="directory\name") signals, fields = wfdb.rdsamp("directory\name", sampfrom=0, sampto="end", channels="all") fs = 2000 t = np.arange(0, len(signals) / fs, 1.0 / fs) plt.plot(t, signals) plt.xlim([540, 545]) plt.title("plot") print("Look at the plots")