This example shows how to explore and test fixed-point designs by distributing tests across
many computers in parallel. The example uses a parfor
loop to test the
accuracy of a QRS detector algorithm. Running parallel simulations requires a Parallel Computing Toolbox™ license.
To run this example, copy the example files to a local working directory.
copyfile(fullfile(matlabroot,'help','toolbox','fixpoint', 'examples',... 'parallel_examples','heart_rate_detector'))
In your local working directory, open and run the test file that runs the example.
edit test_heart_rate_detector_in_parallel.m
test_heart_rate_detector_in_parallel
Like a standard for
-loop,
a parfor
(Parallel Computing Toolbox)-loop executes a series
of statements over a range of values. Using the parfor
command,
you can set up a parallel for
-loop in your code
to explore fixed-point designs by distributing the tests across many
computers. In a parfor
loop, loop iterations
execute in parallel which can provide better performance than standard for
-loops.
This script sets up the system under test, and initializes the
arrays that will contain the results outside of the parfor
-loop.
It then uses a parfor loop to test each record in parallel. The parfor
-loop
loads the data, runs the system, then classifies and saves the results
in parallel. When the parfor
-loop finishes, the
script displays the results. For more information on the system being
tested in this example, see Description of System Under Test.
%% Run test of records in database in parallel record_names = {'ecg_01','ecg_02','ecg_03','ecg_04','ecg_05','ecg_06',... 'ecg_07','ecg_08','ecg_09','ecg_10','ecg_11','ecg_12','ecg_13'}; %% Set up the system under test data_type = 'fixedwrap'; T = heart_rate_detector_types(data_type); [mex_function_name,Fs_target] = setup_heart_rate_detector(record_names,data_type,T); %% Initialize array to contain results results_file_names = cell(size(record_names)); %% Test each record in the database in parallel parfor record_number = 1:length(record_names); % Load data record_name = record_names{record_number}; [ecg,tm,ann,Fs] = load_ecg_data(record_name,Fs_target); % Run system under test detector_outputs = run_heart_rate_detector(mex_function_name,ecg,T); % Classify results [qrs_struct,qrs_stats] = classify_qrs(ann, Fs, detector_outputs); % Save results results_file_names{record_number} = save_heart_rate_data(... mex_function_name,record_name,... data_type,ecg,tm,ann,Fs,... detector_outputs,... qrs_struct,qrs_stats); end %% Display results display_ecg_results(record_names, results_file_names);
Because loop iterations must be completely independent of each
other, you cannot call the save
and load
commands directly inside a parfor
-loop.
You can, however, call functions that call these commands. In this
example, the functions load_ecg_data
and save_heart_rate_data
load
and save the necessary data. For more information on limitations,
see Parallel for-Loops (parfor) (Parallel Computing Toolbox).
The system under test in this example tests a simple QRS detector
that measures the time difference between QRS detections to compute
heart rate. The test_heart_rate_detector_in_parallel
script
passes ECG recordings to the detection algorithm.
The following plot is an example when the detector algorithm correctly identifies the QRS detections to compute the heartbeat.
The detection algorithm is simplified for this example. Examining the plots and results that are displayed when the example runs shows that the algorithm is not always very accurate.
Record #QRS TP FP FN DER Se +P ecg_01 253 195 1 58 23.32 77.08 99.49 ecg_02 133 133 18 0 13.53 100.00 88.08 ecg_03 94 94 1 0 1.06 100.00 98.95 ecg_04 92 91 0 1 1.09 98.91 100.00 ecg_05 93 91 1 2 3.23 97.85 98.91 ecg_06 131 131 22 0 16.79 100.00 85.62 ecg_07 174 173 2 0 1.15 100.00 98.86 ecg_08 117 116 10 1 9.40 99.15 92.06 ecg_09 137 137 1 0 0.73 100.00 99.28 ecg_10 96 96 3 0 3.13 100.00 96.97 ecg_11 73 73 1 0 1.37 100.00 98.65 ecg_12 146 145 71 0 48.63 100.00 67.13 ecg_13 144 144 5 0 3.47 100.00 96.64 Totals 1683 1619 136 62 11.76 96.31 92.25 Legend: #QRS: Total number of QRS Complexes TP: Number of true positive FP: Number of false positive FN: Number of false negative DER: Detection error rate in percent Se: Sensitivity in percent +P: Positive prediction in percent
Note
All ECG recordings used in this example were measured on hobbyist equipment.
You can use the PhysioNet database of recorded physiological signals to do a similar analysis on your own.
The annotations on these recordings were not verified by doctors.
[1] Patrick S. Hamilton, Open Source ECG Analysis Software (OSEA), E.P. Limited, Somerville, MA, http://www.eplimited.com, 2002.
[2] Gari D Clifford, Francisco Azuaje, and Patrick E. McSharry. Advanced Methods and Tools for ECG Data Analysis, Artech House, 2006.
[3] American National Standard ANSI/AAMI EC38:2007 Medical electrical equipment — Part 2–47: Particular requirements for the safety, including essential performance, of ambulatory electrocardiographic systems, Association for the Advancement of Medical Instrumentation, 2008.
[4] George B. Moody, "Evaluating ECG Analyzers", WaveForm DataBase Applications Guide, Harvard-MIT Division of Health Sciences and Technology, Cambridge, MA, WFDB10.5.23, 13 March 2014.
[5] Ida Laila binti Ahmad, Masnani binti Mohamed, Norul Ain binti Ab Ghani, "Development of a Concept Demonstrator for QRS Complex Detection using Combined Algorithms", 2012 IEEE EMBS International Conference on Biomedical Engineering and Sciences, Langkawi, 17th–19th December 2012.
[6] R. Harikumar, S.N. Shivappriya, "Analysis of QRS Detection Algorithm for Cardiac Abnormalities—A Review", International Journal of Soft Computing and Engineering (IJSCE), ISSN: 2231–2307, Volume–1, Issue–5, November 2011.