Often, we have to mark a long trace with labels to indicate positions where we will act in a posterior analysis. To do this, we can maintain a vector of indexes. If we want to create a vector of 20 integers whose value is 0, except at the positions 7, 13 and 19 where it takes value 1 we could do
-->vector = zeros(1,20);
-->vecndx = [7,13,19];
-->vector(vecndx) = 1
vector =
column 1 to 11
! 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. !
column 12 to 20
! 0. 1. 0. 0. 0. 0. 0. 1. 0. !
Now we are going to extract a vector of indexes from `vector'
-->vecndx2 = find (vector > 0) vecndx2 = ! 7. 13. 19. !
We generate a Boolean vector that is true in the positions 7, 13 and 19. The command `find' extracts from this vector those values that are true. The advantage of the procedure is that we extract from a complex (and possibly very long) vector a small set of values containing the information that we are going to use.
Now we use these commands to simulate a `trigger'. We begin with a sinusoid and are interested in the detection of those points at which the signal crosses a trigger level of 0.8. We begin by generating a sinusoid
-->t = 0:1/1000:10; -->s = sin (2 * %pi * 0.4 * t); -->size(s) ans = ! 1. 10001. !
We define a level of 0.8 and are going to extract those positions in `s' whose value is greater than the defined level. We get a Boolean vector but we convert it into a vector of zeros and ones by multiplying by `1'. This vector takes value `1' in all the positions greater than 0.8 in the original vector. As we are interested in the changes, we eliminate the values that do not meet the following conditions: passing from `0' to `1' or from `1' to `0'. As it is a substraction, we insert a first value of `0'. We call this vector `buffer2'. Finally, with the command `find' we extract only positive values, which represent the transition from `0' to `1'.
-->triggerlevel = 0.8; -->buffer = ( s > triggerlevel) * 1; // 1 if greater than level -->buffer2 = [0, buffer(2:$) - buffer(1:$-1)]; // detects changes -->sndx = find (buffer2 > 0); // extracts positive ones -->sndx // indexes sndx = ! 370. 2870. 5370. 7870. !
After these steps we get a vector of only four values. They are the indexes we were trying to find. To check it, we extract the values of the original vector
-->[s(sndx-1);s(sndx)] // pre and post values ans = ! 0.7985515 0.7985515 0.7985515 0.7985515 ! ! 0.8000618 0.8000618 0.8000618 0.8000618 !
Each column represents a transition which fulfills the condition. We can represent a vector containing the sinusoid plus the trigger (figure 7.1).
-->marks = zeros (s); // creates a vector -->marks (sndx) = 1; // introduction of marks -->plot (t, s + (0.4 * marks)) // plots vector and marks
In addition, the times at which transitions are produced are
-->t(sndx) ans = ! 0.369 2.869 5.369 7.869 !
In summary, we have a vector of 10001 values, we apply some processing and get four values that meet the criteria. These values can be used to indicate the points where some other processing can be made. We could apply a similar treatment to the detection of QRS complexes to evaluate the variability of cardiac frequency. To do that, we are going to use `osas.edf'. In the last chapter we stored the list as signals and now it is only necessary to recover the variables stored
-->stacksize(20000000) -->load signals -->ecg = signals (12); -->clear signals
We can detect the points of the QRS complexes by using a trigger level at -150. Afterwards the points stored are used to plot the segments of the signal in a superimpose mode
triggerlevel = -150; // sets trigger
buffer = (ecg<triggerlevel) *1; // array: 1 if ecg < level
// detection points at which buffer changes from 0 to 1
buffer2 = [0, buffer(2:$) - buffer(1:$-1)];
ecgndx = find(buffer > 0); // extracts index
pretrigger = 50; // adjusts points pretrigger
posttrigger = 50; // adjusts points posttrigger
for k=1:20;
trigger = ecgndx(k);
plot2d( [1:pretrigger+posttrigger+1], ...
ecg ( (trigger-pretrigger):(trigger+posttrigger)),...
1, "051", " " ,...
[1,-500,pretrigger+posttrigger+1,500] );
end
The figure represents the superimposition of 20 traces
Of course, the use of a trigger does not warrant that we are detecting QRS complexes. I hope that in future chapters we will be able to filter the signal to detect and recognize more accurately QRS complexes. But I would like to indicate that in a small array we have the points which can be used to