function [co, to, told, fea] = estimateCO(fname,estID,filt_order) % ESTIMATECO Cardiac output estimator. % [CO, TO, TOLD, FEA] = ESTIMATECO(FNAME, ESTID, FILT_ORDER) is the % main function for estimating cardiac output. % % In: FNAME <1xn> --- file where ABP and features are located % ESTID <1x1> --- the CO estimator to use % FILT_ORDER <1x1> --- order of running avg LPF to use on output % (enter 0 or 1 for no LPF) % % Out: CO --- estimated CO (uncalibrated) % TO --- time [minutes] (not evenly sampled!) % TOLD --- time [minutes], not sqi filtered % FEA --- feature matrix % % Usage: % This function is only a wrapper. Actual CO estimation computation is % done in the following required functions: % ESTID 1: est01_MAP - Mean pressure % 2: est02_WK - Windkessel 1st order LTI RC circuit model % 3: est03_SA - Systolic area distributed model % 4: est04_SAwarner - Warner systolic area with time correction % 5: est05_Lilj - Liljestrand PP/(Psys+Pdias) estimator % 6: est06_Herd - Herd estimator % 7: est07_SAwessCI - Wesseling systolic area with impedance correction % 8: est08_Pulsion - Pulsion non-linear compliance model % 9: est09_LidCO - LidCO root-mean-square model % 10: est10_RCdecay - RC exponential decay fit % 11: est11_mf - Wesseling non-linear, time-varying 3-element model % % Written by James Sun (xinsun@mit.edu) on Nov 19, 2005. % - v2.0 - 1/18/06 - added output for detecting percentage of good beats % - v3.0 - 1/20/06 - added "feature" output, CO no longer normalized % load features from fname load(fname,'F','onset','sqi','t0','m2t'); load agegender co = []; to = []; told=[]; fea = []; for seg=1:size(t0,1) % loop through each ABP waveform segment %seg onset1 = onset{seg}; % skip segment if too little data if length(onset1)<50 || length(onset1)<(3*filt_order) continue end % read features F1 = F{seg}; Psys = F1(:,2); Pdias = F1(:,4); PP = F1(:,5); MAP = F1(:,6); Period = F1(:,7); HR = 60*125./Period; tSArr = F1(:,9); SArr = F1(:,10); tSAcosm = F1(:,11); SAcosm = F1(:,12); % select systolic area estimate SA = SArr; tSA = tSArr; % special items for estID 8,9,11 if estID==11 caseid = m2t.caseid; ind = find(agegender(:,1)==caseid); % quit if no age, gender info found if isempty(ind) continue end age = agegender(ind,3); gender = agegender(ind,4); end if estID==8 || estID==9 || estID==11 str = sprintf('load %s abp%d',fname,seg); eval(str); str = sprintf('abp=abp%d; clear abp%d',seg,seg); eval(str); end % estimate CO! switch estID case 1, x = est01_MAP(MAP); case 2, x = est02_WK(PP,HR); case 3, x = est03_SA(SA,HR); case 4, x = est04_SAwarner(SA,HR,onset1,tSA); case 5, x = est05_Lilj(PP,HR,Psys,Pdias); case 6, x = est06_Herd(MAP,Pdias,HR); case 7, x = est07_SAwessCI(MAP,SA,HR); case 8, x = est08_Pulsion(abp, onset1, MAP, HR, tSA); case 9, x = est09_LidCO(abp,onset1,HR); case 10, x = est10_RCdecay(Period,Psys,Pdias,MAP); case 11, x = est11_mf(abp,onset1,MAP,HR,age,gender); case 12, x = est12_coalees(PP,HR,onset1,tSA,Psys,Pdias); case 13, x = est13_trivial(PP,HR,MAP); otherwise, x = nan; end % synchronize time of of all segments offset = (t0(seg,1)-t0(1,1))*24*60; t = onset1(1:end-1)/(125*60)+offset; %[min] % remove all datapoints with bad SQI sqi1 = sqi{seg}(:,1); ind = find(sqi1); t_old = t; x(ind) = []; t(ind) = []; % apply zero-phase moving avg LPF if filt_order<2, x_filt = x; else x_filt = filtfilt(ones(filt_order,1)/filt_order,1,x); end % features ff = F{seg}; ff(ind,:) = []; % append segment data to pool co = [co; x_filt]; to = [to; t]; told = [told; t_old]; fea = [fea; ff]; end % normalize estimated CO to 1st point %co = co/co(1);