2

after doing a some research I reached the point that I decided to ask here for advice as I am not sure how to proceeed.

The problem:

I have an array of RR (IBI) data

Example: [679, 686, 650...]

How can I convert this to heart rate?

My research:

My approach which of course is defective:

for (const ibiInMilliseconds of eventJSONObject.DeviceLog["R-R"].Data) {
      ibiBuffer.push(ibiInMilliseconds);
      const ibiBufferTotal = ibiBuffer.reduce((a, b) => a + b, 0);
      // If adding the ibi to the start of the activity is greater or equal to 2.5 second then empty the buffer there
      if ((lastDate.getTime() + ibiBufferTotal) >= lastDate.getTime() + 2500) {
        const average = ibiBuffer.reduce((total, ibi) => {
          return total + ibi;
        }) / ibiBuffer.length;

        const avg = 1000 * 60 / average; 
        // I save this avg to a 1s list but it's very error prone


        ibiBuffer = [];
        lastDate = new Date(lastDate.getTime() + ibiBufferTotal);
      }
    }

I would appreciate any kind of help or pointers as where to look.

Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117

3 Answers3

1

I think its actually more easy:

 const hearbeats = [];

 let beatCount = 0;
 let time = 0;
 for(const ibi of ibis){
   time += ibi;
   beatCount++;
   if(time > 60 * 1000){
     hearbeats.push(beatCount);
     beatCount = time = 0;
   }
 }

(Disclaimer: i got no idea what im talking about)

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

So far and from what I adopted from @jonas W with fix on the time and conversion to bpm (Heart Rate)

/**
   * Returns an Map of elapsed time and HR from RR data
   * @param rr
   * @param {number} sampleRateInSeconds
   * @return {number[]}
   */
  private static getHRFromRR(rr, sampleRateInSeconds?: number, smoothByAvg?: boolean): Map<number, number> {
    sampleRateInSeconds = sampleRateInSeconds || 10; // Use any second number
    const limit = sampleRateInSeconds * 1000;
    let totalTime = 0;
    let rrBuffer = [];
    return rr.reduce((hr, d) => {
      // add it to the buffer
      rrBuffer.push(d);
      // Increase total time
      totalTime += d;
      // Check if buffer is full
      const time = rrBuffer.reduce((a, b) => a + b, 0); // gets the sum of the buffer [300+600 etc]
      if (time >= limit) {
        if (smoothByAvg) {
          // @todo implement
        } else {
          hr.set(totalTime, rrBuffer.length * 60 / (time / 1000)); // convert to bpm
        }
        rrBuffer = [];
      }
      return hr;
    }, new Map());
  }
Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117
0

After a lot of time testing etc the correct answer is:

/** 
   * Converts the RR array to HR instantaneus (what user sees) 
   * @param rrData 
   * @return {any} 
   */ 
  public static convertRRtoHR(rrData): Map<number, number> { 
    let totalTime = 0; 
    return rrData.reduce((hrDataMap: Map<number, number>, rr) => { 
      totalTime += rr; 
      hrDataMap.set(totalTime, Math.round(60000 / rr)); 
      return hrDataMap; 
    }, new Map()); 
  } 
Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117