Sei sulla pagina 1di 28

Determining the Best Time to Remove a Ventilator from an Apneic Baby Based on Graphs of Biophysical Signal Data vs.

Time
Tom Lever 7 December 2012

Introduction

Neo-natal apnea is the seemingly spontaneous cessation of breathing in premature infants. In hospitals these babies are monitored and supported by ventilators which lead or boost natural breathing. The research of John Delos, Mary Mohr, I, and others focuses on designing a monitor to predict apnea events and to determine accurately whether anomalies in breathing are in fact true apnea events. Our research also focuses on determining when the best time to remove a ventilator from a premature, apneic baby is, to make ventilator removal more successful. To determine the best time to remove a ventilator, we study behaviors of the baby in the day before extubation. These behaviors include: 1. whether extubation (i.e., ventilator removal) was successful (i.e., whether the baby breathed naturally for the forty-eight hours following extubation); 2. the frequency and nature of apnea events and natural breathing; and 3. interactions of baby and ventilator. These baby behaviors are exhibited in graphs of electronic biophysical signals vs. time for the day before extubation (e.g., heart-rate, electrocardiogram, respiration-rate, chest-impedance, oxygen pulse, and probability of apnea signals). My research focuses on producing these graphs to help undergraduate volunteers study these behaviors. What are all the signals graphed? A babys heart rate is the number of heart beats per unit time (beats per minute). An electrocardiogram is a graph of the electrical potential vs. time between two points on a babys chest (volts). The electrocardiogram signal varies with the electrical activity of the heart. According to the National Institute of Health, [1] 1

With each heartbeat, an electrical signal spreads from the top of the heart to the bottom. As it it travels the signal causes the heart to contract and pump blood. The hearts electrical signals set the rhythm of the heartbeat. A babys respiration rate is the number of times a baby inhales per unit time (inhalations per minute). A babys chest impedance is the electrical resistance between two points on the babys chest (ohms). A babys oxygen pulse is the volume of oxygen consumed by the body per heartbeat (liters per heartbeat). The probability of apnea for a baby at any given time is a signal calculated by an algorithm of Delos et al. It is used in hospitals to determine whether a baby is suering apnea and to sound an alarm and used in our research to determine baby behaviors in the day before extubation. Lets study the behavior of a premature, apneic baby supported by a ventilator in the day before extubation. To study the behavior of this baby I will ask and answer a series of questions. Did extubation succeed or fail for this baby? For this baby extubation succeeded. What signals vs. time do the graphs for this baby present? All graphs present, vs. time, from top to bottom: heart rate, the best electrocardiogram for this baby, respiration rate, raw chest impedance, oxygen pulse, singly ltered chest impedance, doubly ltered chest impedance, and probability of apnea. There are 720 graphs for this baby for the day before extubation: each graph spans two minutes in the day before extubation. How do we interpret a graph? To the right of all graphs is a list of possible interpretations, including: 1. Uninterpretable (graph exhibits chaotic behavior); 2. Baby and vent together (baby and ventilator breathing are in phase and periodic); 3. Baby leads vent (baby breathes and ventilator supports every breath, usually with slight delay); 4. Unsynchronized (baby and ventilator breathing are out of phase or are chaotic and show no phase relationship); 5. BETTER: Vent supports baby (baby breathes naturally and ventilator supports every few breaths, in phase); 6. Vent leads baby (ventilator breathes for baby and triggers baby breathing); 7. Baby synchs to vent (we discovered that this is the same as Vent leads baby); and 8. Baby not breathing (vent signal only) (ventilator breathes for baby). We can also interpret the graph as showing the baby to be suering an apnea event. Lets consider a graph (Fig. 1). Which of the 720 graphs for this baby are we looking at? We are looking at graph 251 of 720, beginning fteen hours and twenty-eight minutes before extubation. How do we interpret this graph? In this graph the all signals are chaotic and 2

uninterpretable. The big spike in the blue electrocardiogram signal probably corresponds to the baby moving around and disrupting monitoring.

Figure 1: Signals are uninterpretable. Lets consider another graph (Fig. 2). Which of the 720 graphs are we looking at? We are looking at graph 593 of 720, beginning four hours and fourteen minutes before extubation. How do we interpret this graph? In this graph baby and ventilator breathe together most of the time (the doubly-ltered chest-impedance signal, which varies with baby and ventilator breathing, is sinusoidal: baby and ventilator breathing must be in phase). The baby suers four apnea events (chest impedance at-lines). Toward the end of this graph baby is not breathing (chest-impedance signal is sharp, periodic, and one-third the frequency of babys natural breathing). Note that the probability of apnea signal is zero for these apnea events: the algorithm of Delos et al. fails to lter ventilator breaths and recognize that the baby has ceased breathing. Somebody needs to design a new algorithm to lter ventilator breaths! The next label we want to use to describe one of the graphs for this baby is baby leads ventilator. Because the frequency of ventilator breathing is one third the frequency of babys natural breathing, neither can baby lead ventilator nor can ventilator lead baby. Lets consider another graph (Fig. 3). Which of the 720 graphs are we looking at? We are looking at graph 400 of 720, beginning ten hours and forty minutes before extubation. How do we interpret this graph? At the beginning of this graph the chest-impedance signals are all over the place and uninterpretable. After thirty seconds or so the signals seem more moderate, but are still chaotic: baby and ventilator breathing are unsynchronized. After a minute or so baby and ventilator breathe together. 3

Figure 2: Baby and ventilator breath together, baby suers apnea and stops breathing. Lets consider another graph (Fig. 4). Which of the 720 graphs are we looking at? We are looking at graph 566 of 720, beginning ve hours and eight minutes before extubation. How do we interpret this graph? Recalling that the frequency of ventilator breathing is one third the frequency of babys natural breathing, we notice that throughout this graph one out of every three peaks in the chest-impedance signal is tall and sharp: ventilator supports babys natural breathing. Lets consider a nal graph (Fig. 5). Which of the 720 graphs are we looking at? We are looking at graph 68 of 720, beginning twenty-one hours and forty-four minutes before extubation. I present this graph to demonstrate that the algorithm of Delos et al. sometimes correctly recognizes apnea and how the algorithm calculates probability of apnea. In summary, one goal of our research is to determine the best time to remove a ventilator from an apneic baby by studying behaviors of the baby in the day before extubation, including: whether extubation was successful; the frequency and nature of apnea events and natural breathing; and interactions between baby and ventilator. My research focuses on producing graphs for undergraduate volunteers to study these behaviors.

Figure 3: Baby and ventilator breathing re-synchronize.

Research Log

On Monday, 27 August 2012, Dr. Delos re-introduced me to neo-natal apnea and assigned me to develop a method to collect, read, and analyze data in real time. On Monday, 10 September 2012, Dr. Delos re-assigned me to developing a graphical user interface to help volunteer data analyzers when apneatic babies were breathing naturally and when their respiration was assisted by a ventilator. On Wednesday, 12 September 2012, I met Mary Mohr, a graduate student at William & Mary and a leader in data analysis for this research. Dr. Delos and Mary agreed that I would create graphs of biophysical-signal vs. time data for many babies over the twenty-four hours before extubation (i.e., ventilator removal). These graphs would represent two-minute intervals, to zoom in on signals and make analyzing graphs more manageable. On Friday, 14 September 2012, Dr. Delos and I met to nd me access to SciClones LittleBaby database. Up to this point I was unable to contact Mike Tighe, the custodian of my password to SciClone. I also did not know how to download large sets of data from LittleBaby or how to run Marys analyzing and graphing programs to process data on SciClone. On Monday, 17 September 2012, I met with Mary to learn to navigate SciClone.

Figure 4: Ventilator supports babys natural breathing. On Tuesday, 18 September 2012, Dr. Delos granted me permission to access the LittleBaby database. I downloaded WinSCP, a le-transfer protocol, to download binary data les from SciClone. The LittleBaby database is located at \sciclone\data20\LittleBaby\. The biophysical signal data Im interested in is located in multiple directories within the LittleBaby database. Three electrocardiograms and a raw chest impedance signal are located in the binary les \BedmasterData\NICU XXX\NICU XXX XXXXXXXX wave.bin, with associated index les wave.idx. Heart rate, oxygen pulse, and respiration rate signals are located in the binary les \BedmasterData\NICU XXX\NICU XXX XXXXXXXX vital.bin, with associated index les vital.idx. A singly-ltered chest impedance signal, a doubly-ltered chest impedance signal, a probability of apnea curve, and a signal used to choose the best electrocardiogram signal are located in the binary les \Rusin Server\Batch 37\NICU XXX XXXXXXXX aprob.bin, with associated index les aprob.idx. Not only are signal and time data for various signals dispersed among multiple directories, but also the data are disjointed: the vectors that store the data have dierent lengths and correspond to dierent time periods. Signal data dont always match up with measured points in time and often are missing entirely. In late September I worked to develop various MATLAB programs to neatly parcel disjointed signal and time data into column vectors corresponding one-to-one and to arrange these vectors in a single structure for each baby. I developed a program to plot data from this structure corresponding to the day before extubation and in two-minute segments. I revised 6

Figure 5: Algorithm of Delos et al. recognizes apnea and calculates probability of apnea. this program to format plots and add graphical and textual annotations, including a detailed title and hints for volunteers. Mary sent me two spreadsheets of the IDs, lenames, and extubation times of many babies. One spreadsheet listed babies for whom extubation failed and the other listed babies for whom extubation succeeded. In late October Mary and I worked to iron out my code to correctly read and organize data from the binary les in the LittleBaby database. Mary rewrote our code to correctly enter signal and time data into each babys MATLAB structure. I kept my structure-compiling and plotting programs. Throughout November I turned to Marys spreadsheets. I began processing and checking signal data for babies for whom extubation failed and succeeded. To process data, I download binary and index les for each baby from SciClone, run my reading, compiling, and plotting programs, and check whether all signals are present. Most of the time data les are missing from the LittleBaby database or signals are missing from the binary les. As of today I have successfully generated analyzable plots for ve babies for whom extubation failed and four babies for whom extubation succeeded. I have a lot more data yet to process.

Mechanics of Processing Data

What do I do to process data? I open WinSCP, connect to SciClone, and download binary and index les from the above directories into my local directory C:\NeoNatalApnea\BabiesForWhomExtubationSucceeded\babyXXXX\. I run my programs in this directory. These programs generate \Plots babyXXXX\ containing 720 plots (e.g., NICU XXX XXXXXXX 1.fig), each presenting signal data for two minutes in the day before extubation. These programs also generate babyXXXX.mat, a MATLAB data le containing the structure containing all the signal and time data for babyXXXX. I examine this structure and the plots to determine whether sucient data is presented for volunteers to analyze. I submit satisfactory plots to the oce PC of our research team. How do my programs work? I present them all below. ProcessData is a managing program for my other programs. It takes the names of the binary and index les I downloaded, using them for reading the les and titling the plots. It takes start time and end time, two integers from Marys spreadsheets delimiting the day before extubation for which to process data, corresponding to one day before extubation and extubation, respectively. ProcessData outputs the folder of plots, structure of signal and time data, and .mat le, all mentioned above. GetData reads data from one set of binary les and combines it into a structure of signal and time data. Mary wrote it: I updated it to provide the structure and contents I want. The data for some babies listed in Marys spreadsheets is spread out over multiple sets of wave, vital, and aprob binary les. GetData reads data from one set of binary les and generates one structure of signal and time data. CompileData calls GetData multiple times and combines the single structures into one large structure. It chooses the best electrocardiogram signal to use, looking at the whole, combined structure. It saves the compiled structure to a .mat le. Read Data Segment From BIN File is used by GetData. I dont know who wrote it or how it works. I cant even read the le. PlotData plots signal vs. time data for all two-minute intervals in the twenty-four hours before extubation. It formats, annotates, and organizes the plots. To process data I call, for example, baby6991 = ProcessData( {NICU A4-6350663}, 9104400-86400, 9104400 );

Software for Processing Data

% % % % % % % % % % % % % % % % %

ProcessData.m Author: Tom Lever Updated: Tom Lever, 26 November 2012 A function to manage reading, compiling, and plotting signal vs. time data for a baby. Inputs include all the inputs needed for subfunctions: filenames, a cell array of binary file descriptors (e.g., 'NICU C1970689973'); start time, an integer, corresponding to one day before extubation; and end time, an integer, corresponding to extubation time. Outputs include a folder of plots of signal data vs. time, a large structure of time and signal data, and a .mat file containing this structure.

function baby = ProcessData( filenames, start time, end time )

baby = CompileData( filenames, start time, end time ); PlotData( filenames{1,1}, baby );

end % ProcessData

% % % % % % % % % % % % % % %

CompileData.m Author: Tom Lever Updated: Tom Lever, 26 November 2012 A function to compile the data from multiple sets of wave, vital, and aprob binary files into a one large structure of time and signal data. Inputs include all the inputs needed for subfunctions: filenames, a cell array of binary file descriptors (e.g., 'NICU C1970689973'); start time, an integer, corresponding to one day before extubation; and end time, an integer, corresponding to extubation time.

% Outputs include a large structure of time and signal data and a .mat % file containing this structure.

function baby = CompileData( filenames, start time, end time )

baby = GetData( filenames{1,1}, start time, end time );

for n = 2:length(filenames) nicu = GetData( filenames{1,n}, start time, end time ); baby.time.ekg1 = [baby.time.ekg1, nicu.time.ekg1]; baby.time.ekg2 = [baby.time.ekg2, nicu.time.ekg2]; baby.time.ekg3 = [baby.time.ekg3, nicu.time.ekg3]; baby.time.Chest Impedance ... = [baby.time.Chest Impedance; nicu.time.Chest Impedance]; baby.time.Chest ImpedanceNB ... = [baby.time.Chest ImpedanceNB; nicu.time.Chest ImpedanceNB]; baby.time.HeartRate = [baby.time.HeartRate; nicu.time.HeartRate]; baby.time.RespRate = [baby.time.RespRate; nicu.time.RespRate]; baby.time.PulseOx = [baby.time.PulseOx; nicu.time.PulseOx]; baby.time.HROx = [baby.time.HROx; nicu.time.HROx]; baby.time.EKG ID = [baby.time.EKG ID; nicu.time.EKG ID]; baby.time.CI single filtered ... = [baby.time.CI single filtered; nicu.time.CI single filtered]; baby.time.CI double filtered ... = [baby.time.CI double filtered; nicu.time.CI double filtered]; baby.time.aprob = [baby.time.aprob; nicu.time.aprob]; end % for

% Finds the best electrocardiogram for the combined data baby.data.EKG ID = baby.data.EKG ID( find(baby.data.EKG ID) ); if ( (isempty(baby.data.EKG ID) == 1) ... | | (length(baby.data.EKG ID) == 1) ) baby.data.numberOfBestEKG = 3; baby.time.bestEKG = baby.time.ekg3; baby.data.bestEKG = baby.data.ekg3; else baby.data.numberOfBestEKG = mode(baby.data.EKG ID); switch baby.data.numberOfBestEKG case 1

10

baby.time.bestEKG baby.data.bestEKG case 2 baby.time.bestEKG baby.data.bestEKG case 3 baby.time.bestEKG baby.data.bestEKG end % switch end % if

= baby.time.ekg1; = baby.data.ekg1; = baby.time.ekg2; = baby.data.ekg2; = baby.time.ekg3; = baby.data.ekg3;

% Saves baby to a .mat file. matFileName = filenames{1,1}; matFileName(matFileName == '') = ' '; save(matFileName,'baby');

end

% % % % % % % % % % % %

PlotData.m Author: Tom Lever, based on work by Mary Mohr Updated: Tom Lever, 26 November 2012 A function to plot signal data vs. time for all twominute intervals in the twentyfour hours before extubation. Inputs include baby, a structure containing signal and time data. Outputs include a folder of plots and a zip file of plots within that folder.

function [] = PlotData( filename, baby )

% % Creates directory for plots % directory = pwd; filename(filename == '') = ' '; folderName = ['Plots ', filename]; if ( exist(folderName,'dir') == 0 ) mkdir( folderName ); end % if

11

cd( [directory,'\',folderName] );

% % Plots data vs. time % extubationTime = baby.time.extubationTime; startTimeDay = extubationTime 24*3600; for n = 1:720 startTime = startTimeDay + (n1)*120; endTime = startTime + 120; fprintf( ['\nPlotting data for twominute interval ', num2str(n), '.\n'] ); thisPlot = figure; hold on; grid on;

% % Heart Rate % [, startIndex] = min( abs(baby.time.HeartRatestartTime) ); [, endIndex] = min( abs(baby.time.HeartRateendTime) ); time = baby.time.HeartRate(startIndex:endIndex)extubationTime; data = baby.data.HeartRate(startIndex:endIndex)+300; plot( time, data, 'g' );

% % Best Electrocardiogram % [, startIndex] = min( abs(baby.time.bestEKGstartTime) ); [, endIndex] = min( abs(baby.time.bestEKGendTime) ); time = baby.time.bestEKG(startIndex:endIndex)extubationTime; data = baby.data.bestEKG(startIndex:endIndex)*0.05/2+350; plot( time, data );

% % Respiration Rate % [, startIndex] = min( abs(baby.time.RespRatestartTime) );

12

[, endIndex] = min( abs(baby.time.RespRateendTime) ); time = baby.time.RespRate(startIndex:endIndex)extubationTime; data = baby.data.RespRate(startIndex:endIndex)+250; plot( time, data, 'color', [1,0.5,0] );

% % Chest Impedance, without breath marks % [, startIndex] = min( abs(baby.time.Chest ImpedanceNBstartTime) ); [, endIndex] = min( abs(baby.time.Chest ImpedanceNBendTime) ); time = baby.time.Chest ImpedanceNB(startIndex:endIndex)extubationTime; data = baby.data.Chest ImpedanceNB(startIndex:endIndex)*0.1+240; plot( time, data, 'color', [0,1,0.5] );

% % Oxygen Pulse % [, startIndex] = min( abs(baby.time.PulseOxstartTime) ); [, endIndex] = min( abs(baby.time.PulseOxendTime) ); time = baby.time.PulseOx(startIndex:endIndex)extubationTime; data = baby.data.PulseOx(startIndex:endIndex)+100; plot( time, data, 'c' );

% % Chest Impedance, singlefiltered % [, startIndex] = min( abs(baby.time.CI single filteredstartTime) ); [, endIndex] = min( abs(baby.time.CI single filteredendTime) ); time = baby.time.CI single filtered(startIndex:endIndex)extubationTime; data = baby.data.CI single filtered(startIndex:endIndex)+120; plot( time, data, 'm' );

% % Chest Impedance, doublefiltered % [, startIndex] = min( abs(baby.time.CI double filteredstartTime) ); [, endIndex] = min( abs(baby.time.CI double filteredendTime) ); time = baby.time.CI double filtered(startIndex:endIndex)extubationTime; data = baby.data.CI double filtered(startIndex:endIndex)+80; plot( time, data, 'r' );

13

% Probability of Apnea % [, startIndex] = min( abs(baby.time.aprobstartTime) ); [, endIndex] = min( abs(baby.time.aprobendTime) ); time = baby.time.aprob(startIndex:endIndex)extubationTime; data = baby.data.aprob(startIndex:endIndex); plot( time, data, 'k', 'linewidth', 2 );

% % Modifies plots % startTime = startTime extubationTime; endTime = startTime + 120; xlim([startTime, endTime]); ylim([0,500]);

filename(filename == ' ') = ''; title( [ filename, ', n =' num2str(n) ', t = (' num2str(startTime) ', ' num2str(end filename(filename == '') = ' '; xlabel('Time (s)'); %Use appropriate numbers for y axis ticks set(gca, 'YTickLabel', ' 0 | 1 | | 0 | 1 0 0 | 0 | 5 0 | |100|150| '); %Use x axis ticks spaced 30 seconds set(gca, 'Xtick', startTime:30:endTime); line( [startTime, endTime], [180, 180], ... 'color', 'c', 'linestyle', '.', 'linewidth', 1 ); line( [startTime, endTime], [400, 400], ... 'color', 'g', 'linestyle', '.', 'linewidth', 1 );

%Label the grids for annotation text(endTime+2, 50, 'Baby not breathing'); text(endTime+2, 38, '(vent signal only)'); text(endTime+2, 100, 'Vent leads baby'); text(endTime+2, 150, 'Baby synchs to vent'); text(endTime+2, 200, 'Vent synchs to baby'); text(endTime+2, 250, 'Unsynchronized'); text(endTime+2, 300, 'Baby leads vent'); text(endTime+2, 400, 'Baby and vent'); text(endTime+2, 388, 'together'); text(endTime+2, 450, 'Uninterpretable');

% % Saves plots

14

% plotFileName = [ filename, ' ', num2str(n) ]; saveas(thisPlot, plotFileName); close; end % for

fprintf('\nSaving plots.\n'); zip( folderName, '*.fig' ); cd(directory);

end % PlotDataInTwoMinuteSegments

% % % % % % % % % % % % % %

GetData.m Author: Mary Mohr Updated: Tom Lever, 26 November 2012 One of Mary's programs. Inputs include a filename, a string describing a binary file (e.g., 'NICU C1970689973'); start time, an integer, corresponding to one day before extubation; and end time, an integer, corresponding to extubation time. Outputs include a large structure of time and signal data corresponding to one set of data files, possibly to be combined with other data.

function baby = GetData(filename,start time,end time) %filename (string: NICU ###########), %start time and end time are Doug integer times; time.extubationTime = end time; files=filename; %load rand sample RecNum WAD10 03Feb2011.mat; %cwd=pwd; %for n=1:length(recorded RecNum) for n=1 BedID=filename(find(filename=='N'):find(filename=='')1);

15

ind f=find(filename=='',1,'first'); folder=filename(1:ind f1); %Get Waves & Vitals %cd(['/sciclone/data20/LittleBaby/BedmasterData/' folder]); %Get Waves wid=[1;2;3;4]; binfile=[filename ' wave.bin']; idxfilename=[filename ' wave.idx']; exis=exist(binfile); if exis==0 ind=importdata(idxfilename,'\t'); times=ind(:,1); ind=ind(:,2); [, I]=min(abs(timesstart time)); if times(I)>start time I=I1; end if I<1 I=1; end ind1=ind(I); [, I]=min(abs(timesend time)); if times(I)<end time I=I+1; end if I>length(ind) I=length(ind); end ind2=ind(I); K=ind2ind1; seek=ind1; if K==0 K=inf; end [wdata,t1,t,seek]=readwavebin(binfile,K,seek,wid,start time,end time); fs=wdata(1,1).fs; len=length(wdata(1,1).data)/fs; time.ekg1=t1:1/fs:t1+len1/fs; [, ind1]=min(abs(time.ekg1start time)); [, ind2]=min(abs(time.ekg1end time)); time.ekg1=double(time.ekg1(ind1:ind2)); data.ekg1=wdata(1,1).data; data.ekg1=double(data.ekg1(ind1:ind2));

16

fs=wdata(2,1).fs; len=length(wdata(2,1).data)/fs; time.ekg2=t1:1/fs:t1+len1/fs; [, ind1]=min(abs(time.ekg2start time)); [, ind2]=min(abs(time.ekg2end time)); time.ekg2=double(time.ekg2(ind1:ind2)); data.ekg2=wdata(2,1).data; data.ekg2=double(data.ekg2(ind1:ind2)); fs=wdata(3,1).fs; len=length(wdata(3,1).data)/fs; time.ekg3=t1:1/fs:t1+len1/fs; [, ind1]=min(abs(time.ekg3start time)); [, ind2]=min(abs(time.ekg3end time)); time.ekg3=double(time.ekg3(ind1:ind2)); data.ekg3=wdata(3,1).data; data.ekg3=double(data.ekg3(ind1:ind2)); fs=wdata(4,1).fs; len=length(wdata(4,1).data)/fs; time.Chest Impedance=t1:1/fs:t1+len1/fs; time.Chest Impedance=time.Chest Impedance'; [, ind1]=min(abs(time.Chest Impedancestart time)); [, ind2]=min(abs(time.Chest Impedanceend time)); time.Chest Impedance=double(time.Chest Impedance(ind1:ind2)); time.Chest ImpedanceNB=time.Chest Impedance; data.Chest Impedance=wdata(4,1).data; data.Chest Impedance=double(data.Chest Impedance(ind1:ind2)); %remove breath marks; NB= No Breath marks [data.Chest ImpedanceNB,output marker]=RR2raw V2(data.Chest Impedance); clear wdata t1 %Get Vitals vid=[6;7;8;9]; binfile=[filename ' vital.bin']; idxfilename=[filename ' vital.idx']; exis=exist(binfile); if exis==0 ind=importdata(idxfilename,'\t'); times=ind(:,1); ind=ind(:,2); [, I]=min(abs(timesstart time)); if times(I)>start time I=I1; end if I<1

17

I=1; end ind1=ind(I); [, I]=min(abs(timesend time)); if times(I)<end time I=I+1; end if I>length(ind) I=length(ind); end ind2=ind(I); K=ind2ind1; seek=ind1; if K==0 K = inf; end [vdata,time vital]=readvitalbin(binfile,K,vid,seek); time vital=double(time vital); [, ind1]=min(abs(time vitalstart time)); [, ind2]=min(abs(time vitalend time)); time vital=time vital(ind1:ind2);

data.HeartRate=vdata(:,1); data.HeartRate=double(data.HeartRate(ind1:ind2)); data.RespRate=vdata(:,2); data.RespRate=double(data.RespRate(ind1:ind2)); data.PulseOx=vdata(:,3); data.PulseOx=double(data.PulseOx(ind1:ind2)); data.HROx=vdata(:,4); data.HROx=double(data.HROx(ind1:ind2)); clear vdata %Get Tombstone Data %cd '/sciclone/data20/LittleBaby/Rusin Server/Batches/Batch 37'

[CI filtered time,CI filtered data]=convert bin general segment(filename,st [time double filtered,data double filtered]=convert bin general segment(fil [time aprob,data aprob]=convert bin general segment(filename,start time,end [time EKG ID,EKG ID]=convert bin general segment(filename,start time,end ti %cd '/sciclone/home04/mmohr/data20' data aprob=double(data aprob)/20; CI filtered data=double(CI filtered data)/20; data double filtered=double(data double filtered)/200; time.HeartRate=time vital; time.RespRate=time vital; time.PulseOx=time vital; time.HROx=time vital; time.EKG ID=time EKG ID;

18

data.EKG ID=EKG ID;

time.Chest Impedance; time.CI single filtered=CI filtered time; time.CI double filtered=time double filtered; time.aprob=time aprob;

data.CI single filtered=CI filtered data; data.CI double filtered=data double filtered; data.aprob=data aprob; %cd '/sciclone/home04/mmohr/data20' %filename1=[BedID(6:end) ' ' num2str(start time) '.mat'];

err=0; end end end

baby.time = time; baby.data = data;

end

function [timestamp,signal] = convert bin general segment(filename,start time,end time,sigI %5/17/2012 saves specified signal from file in data files to file in data files\m files %for wave.bin, vital.bin, and aprob.bin files %for all files listed in filenames %filenames is a file containing the names of the files to run %load 'filenames' %len=length(filenames); %assign appropriate suffix to filename based on signal ID switch sigID case {1,2,3,4,5} file suffix=' wave.bin'; case {6,7,8,9} file suffix=' vital.bin'; case {1975,1976,1977,1978,1979,1980} file suffix=' aprob.bin'; end

19

%for all files in listed in the filenames file run the convert bin program %(below) for n=1%:len %file=filenames{n}; filename=[filename file suffix];

[timestamp,signal]=convert bin(filename,start time,end time,sigID);

end end function [timestamp,signal]=convert bin(filename,start time,end time,sigID) %cd '/sciclone/data20/LittleBaby/Rusin Server/Batches/Batch 37' idxfilename=[filename(1:end4) '.idx']; ind=importdata(idxfilename,'\t'); times=ind(:,1); ind=ind(:,2); [, I]=min(abs(timesstart time)); if times(I)>start time I=I1; end if I<1 I=1; end ind1=ind(I); [, I]=min(abs(timesend time)); if times(I)<end time I=I+1; end if I>length(ind) I=length(ind); end ind2=ind(I); fid=fopen(filename); %set the file position indicator to the end of the file fseek(fid,0,1); %return the number of bytes from the beginning of the file ef=ftell(fid); %postition file indicator at I fseek(fid,ind1,1); %read two seconds of data from bin file %cd '/sciclone/home04/mmohr/data20' [timestamp, signal IDs, signal data]=Read Data Segment From BIN File(fid);

20

%in order to preallocate, we estimate how many times Read Data Segment will %run. We call this value pr (probable # of runs). %pos=the position after one run pos=ftell(fid); pos1=posind1; %pr=length of segment/length of one run pr=floor((ind2ind1)/pos1); %find index for signal ID if sigID>=6 && sigID<=9 sigID ind=sigID5; elseif sigID>=1975 && sigID<=1980 sigID ind=sigID1974; else sigID ind=sigID; end signal=signal data{1,sigID ind}; len=length(signal); %timestamp is just one value for the two seconds so we fill in the missing %values timestamp=[timestamp:(2/len):timestamp+2(2/len)]; %preallocate timestamp vector timestamp1=zeros(pr*len,1); %put in the data for the first two seconds timestamp1(1:len)=timestamp(1:len); %preallocate signal vector sig1=ones(pr*len,1)*(32768); %put in the data for the first two seconds sig1(1:len)=signal(1:len); %set counter for runs counter=2; %run until I2 or the end of the file is reached if ind2>ind1 while pos<ef && pos<ind2 [timestamp, signal IDs, signal data]=Read Data Segment From BIN File(fid); signal=signal data{1,sigID ind}; len=length(signal); timestamp=[timestamp:(2/len):timestamp+2(2/len)]; for n=1:len timestamp1((counter1)*len+n)=timestamp(n); sig1((counter1)*len+n)=signal(n); end pos=ftell(fid); counter=counter+1; end else while pos<ef [timestamp, signal IDs, signal data]=Read Data Segment From BIN File(fid); signal=signal data{1,sigID ind};

21

len=length(signal); timestamp=[timestamp:(2/len):timestamp+2(2/len)]; for n=1:len timestamp1((counter1)*len+n)=timestamp(n); sig1((counter1)*len+n)=signal(n); end pos=ftell(fid); counter=counter+1; end end [, ind1]=min(abs(timestamp1start time)); [, ind2]=min(abs(timestamp1end time)); signal=sig1(ind1:ind2); timestamp=timestamp1(ind1:ind2); fclose(fid); end function [wdata,t1,t,seek]=readwavebin(binfile,K,seek,wid,start time,end time) %use K=inf to get all the data %a time vector must be constructed for the wave when done (different %sampling frequencies will have different time vectors) %the time vector can be created thus: %len=length(wdata(#,1).data)/fs; %tvec=t1:1/fs:t1+len1/fs;

if exist('K','var'),K=1000000;end %reads K values, to get the whole file use K=inf, (read segments (using seek output), or op %input the file id for binfile?) if exist('seek','var'),seek=0;end if exist('wid','var'),wid=[1;2;3;4;5;10;11];end %wave id to read, default is all if exist('start time','var'),start time=[];end if exist('end time','var'),end time=[];end t=[]; wdata=[]; t1=[]; %if binfile is a string then open the file and set the file position %indicator at #seek# bytes after the beginning of the file if isstr(binfile) fid=fopen(binfile); if seek>0 fseek(fid,seek,1); end %if binfile is a number then it is the file id and the file is already %opened else fid=binfile; end

22

%if fid=1 the file did not open if fid<0,return,end %read K elements from the file x=fread(fid,K,'int16'); N=length(x); k=5; s=0; start=[]; skip=[]; nseg=[]; while k<=N %s=segment, made up of blocks that have the same length s=s+1; %start is where the segment starts start(s,:)=k4; %?nb=number of blocks? nb=x(k); b=nb+16; nx=b/2; skip(s,:)=nb+8; %used for reading the timestamps %kk gives the index for the nb values until nb changes kk=k:nx:N; j=find(x(kk)=nb,1); if isempty(j),j=length(kk)+1;end ns=j1; nseg(s,:)=ns; %ns is the number of s with the same nb k=kk(ns)+nx; end %disp([start skip nseg]) fseek(fid,seek,1); %set the file position indicator at #seek# bytes after the beginning of the file %read the timestamp for each segment for i=1:s tt=fread(fid,nseg(i),'double',skip(i)); t=[t;tt]; end fclose(fid); if isempty(t),return,end dt=2; %?why 8 first and then 4? seek=start(s)1+(8+skip(s))*nseg(s); if seek>2*N nseg(s)=nseg(s)1; t(end)=[]; seek=start(s)1+(4+skip(s))*nseg(s); end

23

%?why do we subtract dt? t1=min(t)dt; t2=max(t); %if start time or end time values were input use them if they are within %the range if isempty(start time) t1=max(t1,start time); end if isempty(end time) t2=min(t2,end time); end

nt=length(t); wid0=[1;2;3;4;5;10;11]; fs0=[240;240;240;60;120;0;0]; nw=length(wid); ind=zeros(nw,1); %find indices for wid0 that correspond to wid for i=1:nw k=find(wid0==wid(i)); if isempty(k) ind(i)=k; end end %if invalid wave ids were entered there will be ind values of zero, get rid %of these j=find(ind>0); %if there are no indices then return if isempty(j),return,end k=ind(j); wid=wid0(k); %get corresponding fs (sampling frequency) values fs=fs0(k); %bs? (dt=2) bs=dt*fs; %nodata code for ids 15 (32000 for 10&11) nodata=32768; %assign values for id,fs,bs, preallocate data vector for i=1:nw wdata(i,:).id=wid(i); wdata(i).fs=fs(i); wdata(i).bs=bs(i); %time*fs equals length nd=fs(i)*(t2t1); %preallocate data vector using the nodata code wdata(i).data=int16(nodata*ones(nd,1));

24

end k=5; for i=1:nt tt=t(i); if k>N,break,end nb=x(k); b=nb+16; nx=b/2; %so we know how much data to read and where the next segment begins k0=k+5; k1=k5+nx; k=k+nx; %for the next segment if tt<t1 | | tt>t2 continue %proceed to next iteration end %nv=number of vital signs nv=x(k0); %signal ids id=x(k0+(1:nv)); %block size (given in bytes so divide by 2 convert to numbers) ds=x(k0+nv+(1:nv))/2; % off=[cumsum(ds)ds(1); off=[0;cumsum(ds(1:(end1)))]; %kk=indices for data kk=((k0+2*nv+1):k1); data=x(kk); if i==1 %so that it is only displayed once disp([k0 k1 nv length(data)]) disp([id ds off]) end for j=1:length(wdata) kk=find(id==wdata(j).id); if isempty(kk),continue,end %if that id does not exist in the signal then continue if bs(j)==0 bs(j)=ds(kk); fs(j)=bs(j)/dt; disp([wid(j) bs(j) fs(j)]) wdata(j).fs=fs(j); wdata(j).bs=bs(j); nd=fs(j)*(t2t1); wdata(j).data=int16(nodata*ones(nd,1)); end d=data(off(kk)+(1:ds(kk))); %data for id=j i1=round((ttt1)*fs(j)); % i1=bs(j)*(i1); ii=i1+(1:length(d)); wdata(j).data(ii)=d; %put data into wdata end end end

25

function [vdata,t]=readvitalbin(binfile,K,vid,seek) %slightly modified by Mary if exist('vid','var'),vid=[6;7;8;9;12;13;14;15;16];end if exist('K','var'),K=inf;end if exist('seek','var'),seek=0;end t=[]; fid=fopen(binfile); if fid<0,return,end if seek>0 fseek(fid,seek,1); end x=fread(fid,K,'int16'); N=length(x); k=5; s=0; start=[]; off=[]; nseg=[]; while k<=N s=s+1; start(s,:)=k4; nb=x(k); b=nb+16; nx=b/2; off(s,:)=nb+8; kk=k:nx:N; j=find(x(kk)=nb,1); if isempty(j),j=length(kk)+1;end ns=j1; nseg(s,:)=ns; k=kk(ns)+nx; end %disp([start off nseg]) t=[]; fseek(fid,seek,1); for i=1:s tt=fread(fid,nseg(i),'double',off(i)); t=[t;tt]; end fclose(fid); nt=length(t); vdata=int16(ones(nt,length(vid))); k=5; for i=1:nt1 %the 1 was added by Mary, I'm not sure why, there was an error when i=nt tt=t(i); nb=x(k); k0=k+5; b=nb+16;

26

nx=b/2; k=k+nx; nv=x(k0); id=x(k0+(1:nv)); k0=k0+2*nv; data=x(k+(1:nv)); for j=1:length(vid) kk=find(id==vid(j)); if isempty(kk),continue,end vdata(i,j)=x(k0+kk); end

end end function [output RR,output marker]=RR2raw V2(input RR,T,msize,m) %takes the tick marks out if exist('T','var'),T=200;end if exist('msize','var'),msize=128;end if exist('m','var'),m=0;end RR=input RR; n=length(RR); marker=zeros(n,1);

dRR=diff(diff(RR)); dRR=[0;0;dRR(:)]'; j=find(abs(dRR)>T); if m>=1 k=find(diff(j)<=1)+1; for i=1:length(k) jj1=j(k(i))1; d1=dRR(jj11); jj2=j(k(i)); d2=dRR(jj21); if d1*d2<0 jj=jj1:(jj21); marker(jj)=d1; end end else for i=1:length(j) jj1=j(i)1; if marker(jj1)=0,continue,end jj2=jj1+1; if jj2>n,jj2=n;end

27

jj3=jj11; if jj3<1,jj3=1;end d1=dRR(jj1); d2=dRR(jj2); d3=dRR(jj3); if abs(d2)>abs(d3) if d1*d2<0 marker(jj1)=(d1d2)/2; end else if d1*d3<0 marker(jj3)=(d3d1)/2; end end end end output marker = marker; if(length(output marker)=length(input RR)) output marker(length(input RR)+1:end)=[]; end if msize<=0 output RR=input RRoutput marker; else output marker=sign(output marker); output RR=input RR(:)msize*output marker(:); end end % GetData

References
[1] NHLBI, NIH (2010). What is an Electrocardiogram? Accessed http://www.nhlbi.nih.gov/health/health-topics/topics/ekg/, 7 December 2012. at:

28

Potrebbero piacerti anche