<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Analysing a regular ECG signal
In this notebook I'll show you three examples of using HeartPy to analyse good-to-reasonable quality ECG signals you may encounter.
We'll be looking at three excerpts from the European ST-T Database over at Physionet. There are all recorded at 250 Hz
Step1:  Let's look at the first file and visualise it
Step2:  That is a very nice and clean signal. We don't need to do any preprocessing and can run analysis right away
Step3:  That went well.
Now let's move on to the next one and see if we can analyse that one too
Step4:  Ah!
We have an issue where the T-wave (the broad wave right after the main QRS complex) is present. We can filter this using a notch filter, as we're interested in the QRS comples.
What the notch filter does is apply a frequency filter to a very narrow frequency range, allowing us to get rid of some things without disturbing the QRS complexes.
Step5:  We've now reduced the amplitude of the T-wave and are ready for analysis
Step6:  Oh dear
HeartPy is distrusting some peaks. This is because HeartPy's optimizer likes broader peaks than some ECG recordings provide (especially lower sampling rates). Usually when filtering the peak width decreases as well, potentially causing issues. 
The solution is simple. We can upsample the signal using scipy.signal.resample to help with this!
Step7:  Upsampling the signal has enabled HeartPy to optimize and find the position for all peaks in the signal.
Note the use of hp.scale_data() in the processing function. This is recommended when the amplitude is low (2.4-3.8 in the original data).
Let's look at the last example
Step8:  Again we have a very strong signal present in the recording. That is always nice to see. Analysis again is then straightforward
Step9:  And again we can fix the 'mistrusted' peaks with modest upsampling
Step10:  Since 1.2.4 HeartPy includes Poincaré nonlinear methods too
Use them like the plotter function
<ASSISTANT_TASK:>
Python Code:
#import packages
import heartpy as hp
import matplotlib.pyplot as plt
sample_rate = 250
Explanation: Analysing a regular ECG signal
In this notebook I'll show you three examples of using HeartPy to analyse good-to-reasonable quality ECG signals you may encounter.
We'll be looking at three excerpts from the European ST-T Database over at Physionet. There are all recorded at 250 Hz
End of explanation
data = hp.get_data('e0103.csv')
plt.figure(figsize=(12,4))
plt.plot(data)
plt.show()
Explanation: Let's look at the first file and visualise it:
End of explanation
#run analysis
wd, m = hp.process(data, sample_rate)
#visualise in plot of custom size
plt.figure(figsize=(12,4))
hp.plotter(wd, m)
#display computed measures
for measure in m.keys():
    print('%s: %f' %(measure, m[measure]))
Explanation: That is a very nice and clean signal. We don't need to do any preprocessing and can run analysis right away:
End of explanation
data = hp.get_data('e0110.csv')
plt.figure(figsize=(12,4))
plt.plot(data)
plt.show()
#and zoom in a bit
plt.figure(figsize=(12,4))
plt.plot(data[0:2500])
plt.show()
Explanation: That went well.
Now let's move on to the next one and see if we can analyse that one too:
End of explanation
filtered = hp.filter_signal(data, cutoff = 0.05, sample_rate = sample_rate, filtertype='notch')
#visualize again
plt.figure(figsize=(12,4))
plt.plot(filtered)
plt.show()
#and zoom in a bit
plt.figure(figsize=(12,4))
plt.plot(data[0:2500], label = 'original signal')
plt.plot(filtered[0:2500], alpha=0.5, label = 'filtered signal')
plt.legend()
plt.show()
Explanation: Ah!
We have an issue where the T-wave (the broad wave right after the main QRS complex) is present. We can filter this using a notch filter, as we're interested in the QRS comples.
What the notch filter does is apply a frequency filter to a very narrow frequency range, allowing us to get rid of some things without disturbing the QRS complexes.
End of explanation
#run analysis
wd, m = hp.process(hp.scale_data(filtered), sample_rate)
#visualise in plot of custom size
plt.figure(figsize=(12,4))
hp.plotter(wd, m)
#display computed measures
for measure in m.keys():
    print('%s: %f' %(measure, m[measure]))
Explanation: We've now reduced the amplitude of the T-wave and are ready for analysis
End of explanation
from scipy.signal import resample
#resample the data. Usually 2, 4, or 6 times is enough depending on original sampling rate
resampled_data = resample(filtered, len(filtered) * 2)
#And run the analysis again. Don't forget to up the sample rate as well!
wd, m = hp.process(hp.scale_data(resampled_data), sample_rate * 2)
#visualise in plot of custom size
plt.figure(figsize=(12,4))
hp.plotter(wd, m)
#display computed measures
for measure in m.keys():
    print('%s: %f' %(measure, m[measure]))
Explanation: Oh dear
HeartPy is distrusting some peaks. This is because HeartPy's optimizer likes broader peaks than some ECG recordings provide (especially lower sampling rates). Usually when filtering the peak width decreases as well, potentially causing issues. 
The solution is simple. We can upsample the signal using scipy.signal.resample to help with this!
End of explanation
data = hp.get_data('e0124.csv')
plt.figure(figsize=(12,4))
plt.plot(data)
plt.show()
#and zoom in a bit
plt.figure(figsize=(12,4))
plt.plot(data[0:2500])
plt.show()
Explanation: Upsampling the signal has enabled HeartPy to optimize and find the position for all peaks in the signal.
Note the use of hp.scale_data() in the processing function. This is recommended when the amplitude is low (2.4-3.8 in the original data).
Let's look at the last example
End of explanation
#run analysis
wd, m = hp.process(hp.scale_data(data), sample_rate)
#visualise in plot of custom size
plt.figure(figsize=(12,4))
hp.plotter(wd, m)
#display computed measures
for measure in m.keys():
    print('%s: %f' %(measure, m[measure]))
Explanation: Again we have a very strong signal present in the recording. That is always nice to see. Analysis again is then straightforward:
End of explanation
#resample the data. Usually 2, 4, or 6 times is enough depending on original sampling rate
resampled_data = resample(data, len(filtered) * 2)
#And run the analysis again. Don't forget to up the sample rate as well!
wd, m = hp.process(hp.scale_data(resampled_data), sample_rate * 2)
#visualise in plot of custom size
plt.figure(figsize=(12,4))
hp.plotter(wd, m)
#display computed measures
for measure in m.keys():
    print('%s: %f' %(measure, m[measure]))
Explanation: And again we can fix the 'mistrusted' peaks with modest upsampling
End of explanation
hp.plot_poincare(wd, m)
#print poincare measures
poincare_measures = ['sd1', 'sd2', 's', 'sd1/sd2']
print('\nnonlinear poincare measures:')
for measure in poincare_measures:
    print('%s: %f' %(measure, m[measure]))
Explanation: Since 1.2.4 HeartPy includes Poincaré nonlinear methods too
Use them like the plotter function:
End of explanation
<END_TASK>