ECG-Kit 1.0
(5,648 bytes)
classdef ECGtask_PCA_proj_basis < ECGtask
% ECGtask for ECGwrapper (for Matlab)
% ---------------------------------
%
% Description:
%
% Abstract class for defining ECGtask interface
%
%
% Author: Mariano Llamedo Soria (llamedom at {electron.frba.utn.edu.ar; unizar.es}
% Version: 0.1 beta
% Birthdate : 18/2/2013
% Last update: 18/2/2013
properties(GetAccess = public, Constant)
name = 'PCA_proj_basis';
target_units = 'ADCu';
doPayload = false;
end
properties( GetAccess = public, SetAccess = private)
% if user = memory;
% memory_constant is the fraction respect to user.MaxPossibleArrayBytes
% which determines the maximum input data size.
memory_constant = 0.3;
started = false;
end
properties( Access = private, Constant)
%sample 10 minutes from the whole recording.
time_sample = 10 * 60; %seconds
time_heartbeat_window = 2; %seconds around the heartbeat
end
properties( Access = private )
ECG_slices
QRS_sample_idx
wavelet_filters
some_window
halfwin_samples
end
properties
progress_handle
cant_QRS_locations
autovec
tmp_path
end
methods
function obj = ECGtask_PCA_proj_basis(obj)
obj.ECG_slices = [];
end
function Start(obj, ECG_header, ECG_annotations)
% ECG cell for grouping QRS complex slices
obj.ECG_slices = [];
% Sample which QRS complexes will consider into de PCA basis
% calculation
cant_QRS_sample = round(obj.time_sample / obj.time_heartbeat_window);
cant_QRS = length(ECG_annotations.time);
obj.QRS_sample_idx = sort(randsample(cant_QRS, min(cant_QRS,cant_QRS_sample)));
obj.halfwin_samples = round( obj.time_heartbeat_window/2*ECG_header.freq);
obj.some_window = colvec(blackman(2*obj.halfwin_samples+1));
obj.started = true;
end
function payload = Process(obj, ECG, ECG_start_offset, ECG_sample_start_end_idx, ECG_header, ECG_annotations, ECG_annotations_start_end_idx )
% this object doesn't generate any payload
payload = [];
if( ~obj.started )
obj.Start(ECG_header);
if( ~obj.started )
cprintf('*[1,0.5,0]', 'Task %s unable to be started for %s.\n', obj.name, ECG_header.recname);
return
end
end
this_iter_QRS_sample_idx = find(obj.QRS_sample_idx >= ECG_annotations_start_end_idx(1) & obj.QRS_sample_idx <= ECG_annotations_start_end_idx(2));
if( ~isempty(this_iter_QRS_sample_idx) )
% change the reference to this iteration
this_iter_QRS_sample_idx = obj.QRS_sample_idx(this_iter_QRS_sample_idx) - ECG_annotations_start_end_idx(1) + 1;
QRS_locations = ECG_annotations.time;
this_iter_ECG_size = size(ECG,1);
ECG = int16(round(BaselineWanderRemovalSplines( double(ECG), QRS_locations, ECG_header.freq)));
aux_idx = arrayfun(@(a)( max(1, QRS_locations(a) - obj.halfwin_samples): ...
min( this_iter_ECG_size, QRS_locations(a) + obj.halfwin_samples)) , ...
colvec(this_iter_QRS_sample_idx), 'UniformOutput', false);
aux_idx3 = 1:(2*obj.halfwin_samples+1);
aux_idx2 = arrayfun(@(a)( aux_idx3( ...
(max(1, QRS_locations(a) - obj.halfwin_samples): ...
min( this_iter_ECG_size, QRS_locations(a) + obj.halfwin_samples)) ...
- max(1, QRS_locations(a) - obj.halfwin_samples) + 1 ) ), ...
colvec(this_iter_QRS_sample_idx), 'UniformOutput', false);
obj.ECG_slices = [obj.ECG_slices; cellfun(@(a,b)( int16(round(bsxfun(@times, double(ECG(a,:)), obj.some_window(b) ))) ), aux_idx, aux_idx2, 'UniformOutput', false)];
end
end
function payload = Finish(obj, payload, ECG_header)
ECG = cell2mat(obj.ECG_slices);
% Wavelet transform calculation
wtECG = int16(round(qs_wt(double(ECG), 4, ECG_header.freq, obj.wavelet_filters)));
% calculate PCA in wt scale 4 of the ECG
WTecg_cov = obj.my_mcdcov( double(wtECG) );
[obj.autovec autoval] = eig(WTecg_cov);
autoval = diag(autoval);
[~, autoval_idx] = sort(autoval, 'descend');
obj.autovec = obj.autovec(:,autoval_idx);
end
function payload = Concatenate(obj, plA, plB)
payload = [];
% not implemented
end
end
methods ( Access = private )
function cov_mat = my_mcdcov(obj, x)
result = mcdcov(x, 'plots', 0);
cov_mat = result.cov;
end
end
end