I'm working on an application that reads the heart cycle from a device, and I've aimed to get this image:

enter image description here

Now, I need to get the highest points that appear in every cycle in order to calculate the period from diastole or systole, but the problem is that every period can be placed on a different y-axis range.

How can I find the highest points with math or statistics without performing comparisons to software level?

I need to know how often the high points are.


You're receiving a stream of data coming in at what should be a constant time-step. The solution is to use a FIFO (First In First Out) algorithm.

  1. Feed the data into a buffer. As new data comes in, old data gets pushed out. You have a constant amount of data in there (except in the beginning when it's filling up eventually).

  2. Depending on the granularity of the device's time-step, select an appropriate interval (number of time-steps). How prominent must the peak be for it to be considered a heartbeat? This will decide the interval size. You probably don't want to pick an interval that's too small - hiccups in the data may incorrectly register as heartbeats. You also don't want it too big - two peaks may be competing for the same heartbeat status when they really both should get it.

  3. Every time a new tick of data is received and put into the buffer, calculate the maximum of all the ticks and record which one it is.

  4. If a piece of data enters and exits and remains the maximum point the whole time, you've got a heartbeat.

Here's a visual representation of how it works:

enter image description here

  • Blue is the heartbeat data coming in
  • Green is the buffer size
  • Arrows show direction data is going
  • Red shows peaks. The one in the green zone is a candidate. Once it gets out, you know it's a peak.

From here you can add all sorts of nifty features to optimize and correct for errors.

  • Calculate a running frequency of heartbeats and adjust your buffer size as you go. If you sense the heartbeat is slowing down, make the buffer larger so you can search appropriately for heartbeats, and vice versa if it's speeding up.

  • If you happen to record peaks that are too too close together, or if you don't record a heartbeat after a certain amount of time, alert the user!

  • A total buffer size that covers somewhat over half in both direction is a good starting point. When you code this, the buffer will be a bit over one quarter - the point must be a maximum for 25+% in both directions (giving you the total of over a half).

  • Implementation tip: A peak is only a peak if it enters the buffer and is immediately the top point and stays that way until the end.

  • You can optimize this further so it only tracks two data points (current maximum and the next new data tick) instead of the whole buffer.

  • You can also use this method to find minimum points.

| cite | improve this answer | |

I would use a Fourier transform to first filter out all the low frequencies (i.e the average y-value), so that you are left with a function that is more or less periodic. Now, you look for points who's y-values on each side are smaller than itself to find maximum (diastole?) points in each cycle.

| cite | improve this answer | |
  • $\begingroup$ Points may be incorrectly labeled as peaks by that method - look how the graph sharply rises and then goes down in a jagged fashion after. Plus if you're going on a point-by-point basis like that, why do the FT? $\endgroup$ – GraphicsMuncher Jul 8 '13 at 14:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.