You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
how can I get cardioid graph from ecg QRS complex?
5 views (last 30 days)
Show older comments
HI, CAN ANYONE SHOW ME HOW SHOULD I GET CARDIOD GRAPH FROM QRS COMPLEX?
Accepted Answer
Star Strider
on 5 Oct 2016
The plot you want is called a vectorcardiogram. You need an EKG record that is noise-free and has baseline offset and baseline variation removed. Use Lead I and Lead aVF records to plot it. See Detecting QRS complex in ECG signal for details. My ‘EKG_Explore.m’ function (attached to my initial Answer) should provide you with guidance on how to program it.
26 Comments
Star Strider
on 9 Nov 2016
It shouldn’t have ‘N’ columns, it should have 6 or 12. You have to see the PhysioNet documentation for that file to understand what’s in it, since I have no idea. There are probably hundreds of files on PhysioNet.
If it’s only a rhythm strip, it’s likely a Lead II, and you won’t be able to create a vectorcardiogram from it. You have to have at least a 6 lead EKG, since you need Lead I and Lead aVF to create your vectorcardiogram. If you want to upload the ‘.mat’ file here (use the ‘paperclip’ icon), I’ll take a look at it. (That’s not a problem as far as PhysioNet is concerned. It’s an open site.)
Neal
on 9 Nov 2016
Edited: Neal
on 9 Nov 2016
Thanks strider for your reply, I have attached a file,please check it. After compression technique(DWT), in order to generate cardioid graph two sets of points are required. The QRS amplitude considered as vector x, and their differentiated value as vector y. With these vectors x & y closed loop plot is generated which resembles a cardioid shape.(described by previous author research paper).plz help me out of this. How can I solved this problem? The author also used this database which is described in his paper.Still now I am not starting this project.
Star Strider
on 9 Nov 2016
It’s a Lead II rhythm strip (without a time vector or sampling frequency). You need at least a 6-lead EKG to do what you want. PhysioNet has several of these, so find one that does what you want (NSR, Atrial Fibrillation, etc.) download the ‘.mat’ file, upload it here, and I’ll see what I can do. Please also include the sampling frequency so I can create a time vector from it.
Star Strider
on 9 Nov 2016
You need to search PhysioNet for 6- or 12 lead EKGs.
The leads will be labeled I, II, III, aVR, aVL, aVF, and V1 through V6, possibly including V3R. You need to look for records with those leads.
Star Strider
on 9 Nov 2016
PhysioNet has them. You have to choose the one that meets your needs. Upload it here, and after that, I can help you with the analysis.
Star Strider
on 9 Nov 2016
That EKG demonstrates atrial fibrillation with multifocal junctional and ventricular PVCs. There are no normal P-QRS-T complexes that I can identify. Please see if you can find a normal sinus rhythm 6- or 12-lead EKG.
The code I used to filter and display Lead I is:
D = load('sourav I18m.mat');
EKG = D.val;
Fs = 256; % Sampling Frequency (Guess)
Fn = Fs/2; % Nyquist Frequency
Ts = 1/Fs; % Sampling Interval
t = linspace(0, 1, size(EKG,2))*Ts; % Time Vector
Wp = [2 40]/Fn; % Passband
Ws = [1 50]/Fn; % Stopband
Rp = 5; % Passband Ripple
Rs = 20; % Stopband Ripple
[n,Wn] = buttord(Wp,Ws,Rp,Rs); % Butterworth Filter Order
[b,a] = butter(n,Wn); % Butterworth Filter Transfer Function Coefficients
[SOS,G] = tf2sos(b,a); % Convert to Second-Order-Section For Stability
figure(1)
freqz(SOS, 4096, Fs) % Assess Filter
EKGf = filtfilt(SOS,G,EKG')'; % Filter EKGs
figure(2)
plot(t, EKGf(1,:))
grid
axis([[0 0.001]+0.0025 ylim])
Star Strider
on 10 Nov 2016
Unfortunately, no. To plot a complete vectorcardiogram, you have to have at least one normal identifiable P-QRS-T complex. I searched the database and managed to find a normal EKG record (attached). It reads, filters, and plots the scalar and vector EKG.
The Code —
D = load('EKG_0319214B-1559-4B14-8252-6659E91A480Dm.mat');
EKG = D.val;
Fs = 1000; % Sampling Frequency (Guess)
Fn = Fs/2; % Nyquist Frequency
Ts = 1/Fs; % Sampling Interval
t = linspace(0, 1, size(EKG,2))*Ts; % Time Vector
Wp = [2 40]/Fn; % Passband
Ws = [1 60]/Fn; % Stopband
Rp = 5; % Passband Ripple
Rs = 20; % Stopband Ripple
[n,Wn] = buttord(Wp,Ws,Rp,Rs); % Butterworth Filter Order
[b,a] = butter(n,Wn); % Butterworth Filter Transfer Function Coefficients
[SOS,G] = tf2sos(b,a); % Convert to Second-Order-Section For Stability
figure(1)
freqz(SOS, 4096, Fs) % Assess Filter
EKGf = filtfilt(SOS,G,EKG')'; % Filter EKGs
figure(2)
for k1 = 1:size(EKGf,1) % Plot All Records
subplot(size(EKGf,1), 1, k1)
plot(t, EKGf(k1,:))
grid
axis([[0 2E-4]+0.0 ylim])
end
idx0 = find(t <= 0.40E-4, 1, 'last'); % Define Segments By Index
idx1 = find(t <= 0.55E-4, 1, 'last');
idx2 = find(t <= 0.70E-4, 1, 'last');
idx3 = find(t <= 1.20E-4, 1, 'last');
figure(3) % Plot Loops
plot(EKGf(2,idx0:idx1), EKGf(7,idx0:idx1))
hold on
plot(EKGf(2,idx1:idx2), EKGf(7,idx1:idx2))
plot(EKGf(2,idx2:idx3), EKGf(7,idx2:idx3))
hold off
axis equal
legend('P', 'QRS', 'T', 'Location','NE')
title('Frontal Vectorcardiogram - Segment Loops')
u = -gradient(EKGf(2,:));
v = -gradient(EKGf(7,:));
figure(4) % Plot Direction Vectors
quiver(EKGf(2,idx0:idx1), EKGf(7,idx0:idx1), u(idx0:idx1), v(idx0:idx1))
hold on
quiver(EKGf(2,idx1:idx2), EKGf(7,idx1:idx2), u(idx1:idx2), v(idx1:idx2))
quiver(EKGf(2,idx2:idx3), EKGf(7,idx2:idx3), u(idx2:idx3), v(idx2:idx3))
hold off
axis equal
legend('P', 'QRS', 'T', 'Location','NE')
title('Frontal Vectorcardiogram - Direction of Action Propagation')
-----------------------------------------------------------
figure(4) —
Neal
on 15 Nov 2016
Edited: Walter Roberson
on 15 Nov 2016
D = load('EKG_0319214B-1559-4B14-8252-6659E91A480Dm.mat');
EKG = D.val;
Fs = 1000; % Sampling Frequency (Guess)
Fn = Fs/2; % Nyquist Frequency
Ts = 1/Fs; % Sampling Interval
t = linspace(0, 1, size(EKG,2))*Ts; % Time Vector
Wp = [2 40]/Fn; % Passband
Ws = [1 60]/Fn; % Stopband
Rp = 5; % Passband Ripple
Rs = 20; % Stopband Ripple
[n,Wn] = buttord(Wp,Ws,Rp,Rs); % Butterworth Filter Order
[b,a] = butter(n,Wn); % Butterworth Filter Transfer Function Coefficients
[SOS,G] = tf2sos(b,a); % Convert to Second-Order-Section For Stability
figure(1)
freqz(SOS, 4096, Fs) % Assess Filter
EKGf = filtfilt(SOS,G,EKG')';
when I plot this 12 lead ecg with sampling frequency 1000 i can't get anything , why?
Star Strider
on 15 Nov 2016
If you ran only that section of the code, you will only see the Bode plot of the filter. You have to run the entire code to see all the plots.
My code ran successfully as posted (I am running R2016b), and produced the correct plots. I posted only the last one, since it is the most informative. (The P and T loops also display the quiver arrows, but you have to zoom the plot to see them.)
Star Strider
on 17 Nov 2016
First, a bit about electrocardiography and the cardiac excitation cycle. Briefly, it begins with the sinoatrial node initiating the P-wave (atrial depolarization) that then goes to the Bundle of His before it is transmitted to ventricles to create the QRS complex (ventricular depolarization), then the ventricular myocardium re-polarizes, creating the T-wave.
I visually identified the three segments (P, QRS, T) in one complete cycle by time, and then used the find command to determine the indices (in idx0 through idx3) corresponding to those times. I used Lead I and Lead aVF to create the plot, row 2 of the EKG record being Lead I and row 7 being Lead aVF. I then just plotted the segments from those two leads against each other for each segment to create the three loops, since those two leads are perpendicular to each other in the frontal plane. (I could have plotted the entire cycle as one plot but chose to break it up into the three segments plotted in different colours for clarity.) I used the hold function to plot all three segments on the same axes. Using the axes equal function guaranteed that the units in the x-direction are the same as the units in the y-direction to avoid distortion in the plot. See the documentation on legend and title for descriptions of those functions.
In figure(4), I plotted the vectors as the direction of propagation of each part of the cycle, using the gradient function to create the direction vectors. (The arrows in the P and T waves are visible, but you have to zoom in to see them.) Note that the right ventricle depolarizes first, this is due to its having less muscle mass than the left ventricle. The two ventricles contract almost simultaneously as the result.
Note that this is a healthy heart from an antiarrhythmic drug trial. The EKG has a normal configuration and normal intervals.
Neal
on 19 Nov 2016
I have attached a file of ECG, can you tell me how can i detect R-peak and QRS segmentation from this database?
Star Strider
on 19 Nov 2016
That is a distinctly abnormal EKG, and exhibits a left anterior fascicular block pattern. Without the time vector it’s not possible to determine the width of the QRS complex, but it demonstrates the characteristic notch R-wave in Lead V1, and the notched S-wave in Lead V6.
First, you need to see the accompanying ‘.info’ file to determine the sampling frequency and amplification scaling. Without those, you can go no further.
Second, you need to use the bandpass filter I designed to eliminate the baseline drift.
Third, it’s clean enough so that you can then use the findpeaks function to locate the P, R, and T waves. You will need to experiment with the name-value pairs in the findpeaks function, along with using thresholds and the set function setdiff and possibly others to correctly isolate the various components of the cardiac electrophysiologic cycle.
I wrote this code to display the unfiltered and unscaled EKG. When you filter it and scale it, you will have to change the axis x-axis limits in figure(1):
D = load('Neal ptb.mat');
EKG = D.val;
[EKGr,EKGc] = size(EKG);
Leads = {'I','II','III','aV_R','aV_L','aV_F','V_1','V_2','V_3','V_4','V_5','V_6'};
q2 = [];
figure(1)
k3 = 1;
for k1 = 0 : 2
for k2 = [1 4 7 10]
q2 = [q2 k1+k2];
subplot(3, 4, k3)
plot(EKG(k1+k2,:))
grid
axis([0 2000 ylim])
title(Leads{k1+k2})
k3 = k3+1;
end
end
windw = 100 : 700;
figure(2)
plot(EKG(1,windw), EKG(6,windw))
grid
axis equal
title('Frontal Plane Vectorcardiogram')
u = -gradient(EKG(1,windw));
v = -gradient(EKG(7,windw));
w = -gradient(EKG(6,windw));
windw = 100 : 700;
figure(3)
quiver3(EKG(1,windw), EKG(7,windw), EKG(6,windw), u, v, w)
grid on
axis equal
title('3D Vectorcardiogram')
Compare figure(2) here with the previous plot to see the effects of a left anterior fascicular block on the ventricular depolarisation sequence. Note in figure(3) that the right ventricle depolarises normally, then the depolarisation sequence shifts to the intact left posterior fascicle, with the anterior of the left ventricle depolarising later.
(This is something of a digression, but I really get off on this stuff!)
Star Strider
on 20 Nov 2016
Use:
Fs = 356;
with my code. The rest of the filter design and signal filtering and display code should work without modification.
Neal
on 21 Nov 2016
Edited: Neal
on 21 Nov 2016
%
D = load('EKG_0319214B-1559-4B14-8252-6659E91A480Dm.mat');
EKG = D.val;
Fs = 1000; % Sampling Frequency (Guess)
Fn = Fs/2; % Nyquist Frequency
Ts = 1/Fs; % Sampling Interval
t = linspace(0, 1, size(EKG,2))*Ts; % Time Vector
figure(1)
plot(t,EKG)
Wp = [2 40]/Fn; % Passband
Ws = [1 60]/Fn; % Stopband
Rp = 5; % Passband Ripple
Rs = 20; % Stopband Ripple
[n,Wn] = buttord(Wp,Ws,Rp,Rs); % Butterworth Filter Order
[b,a] = butter(n,Wn); % Butterworth Filter Transfer Function Coefficients
[SOS,G] = tf2sos(b,a); % Convert to Second-Order-Section For Stability
figure(2)
freqz(SOS, 4096, Fs) % Assess Filter
EKGf = filtfilt(SOS,G,EKG')';
figure(3)
plot(t,EKGf)
I have plotted EKGf, If I want to plot fresh signal from EKGf then what should I do?
Star Strider
on 21 Nov 2016
First, check your sampling frequency. Usual sampling frequencies for the PhysioNet Database are 256 Hz and 1000 Hz. A sampling frequency of 356 Hz is unusual.
Second, once you have ‘EKGf’, and if it is a full 12-lead EKG, probably the best way to display it is with the code in my Comment of 19 Nov 2016 at 15:08. That will display all 12 leads, the frontal vectorcardiogram, and the full 3D vectorcardiogram.
To use it, delete the first line (the load call) and substitute the second line:
EKG = D.val;
with:
EKG = EKGf;
Neal
on 10 Dec 2016
Can you tell me which is the feature vector of QRS complexes(that you has posted on 10 Nov 2016), for training process.
Star Strider
on 10 Dec 2016
I have not ever attempted to use EKG vectors for training neural nets or other machine-learning algorithms.
I recommend that you search PubMed to see what other investigators have done in this area. I know this is an area of active research (or once was). It is not an area I ever got involved with.
Neal
on 11 Dec 2016
Thanks for the information. can you tell me how the cardiod(loop) has plotted mathemetically. I want to know the mathematical expression to plot cardiod graph).
Star Strider
on 11 Dec 2016
My pleasure.
My code explains the plot clearly. There are three essentially orthogonal leads — I, aV_F, and V_2. The first two define the ‘+x’- and ‘-z’ directions in the frontal plane, and the third in the ‘+y’ direction, providing 3D reference coordinates. Plotting the first two create the 2D frontal vectorcardiogram loop, and adding the third creates it in 3D. All EKG leads have a common centre reference that is created within the EKG recording system electronics. The common zero origin of the plots is defined anatomically as the sinoatrial node, where the ‘pacemaker’ signal originiates. I refer you to John Webster’s textbook on biomedical instrumentation (there are likely others as well) for a thorough discussion.
As far as plotting it, that is simply plotting the EKG leads at corresponding time points. The activation sequence to plot the arrows in the quiver plots require the negative of the gradient simply because the way the vectors are defined in the quiver plots.
So the vectorcardiogram is not defined mathematically beyond the description I provided here. It is defined by the heart, and the way MATLAB plots the data. Mathematical simulations of the P-QRS-T complex are far beyond the scope of anything I want to get into here. The separation of the full activation and depolarisation sequence into its components I did visually. The mathematics of that is the subject of myriad publications. Considering that algorithms to do that have to recognise normal as well as abnormal rhythms and activation sequences makes this an extremely difficult problem. It is often difficult to do manually in extreme deviations from a normal, healthy heart.
More Answers (0)
See Also
Categories
Find more on Spectral Measurements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)