Exemple #1
0
 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")
Exemple #4
0
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/')
Exemple #6
0
 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)
Exemple #8
0
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
Exemple #10
0
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)
Exemple #12
0
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)
Exemple #13
0
            #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])
Exemple #14
0
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)
Exemple #15
0
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)
Exemple #16
0
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")