Skip to content

Effect of disturbances on longest run length estimation in VF/AF rhythm #33

@jcbsv

Description

@jcbsv

Dear George,

I am studying the code in the rxr.c app, and in particularly the find_longest_run function, which includes the following while-loop to "find the first annotation at or beyond t0":

find_longest_run(a, t0, t1, type)
unsigned int a;
WFDB_Time t0, t1;
int type;	/* 0: find VE run; 1: find SVE run */
{
    int am, len = 0, len0 = 0;
    /* If a VF (AF) episode started before t0 and ends after t0, simply return
       6 (the maximum run length considered by this program). */
    if (f_end < 0L || f_end > t0) return (6);

    /* If there are no more annotations for annotator a, simply return 0. */
    if (annot[a].time < 0L) return (0);

    /* Otherwise, find the first annotation at or beyond t0. */
    while (annot[a].time < t0) {
	if ((type == 0 && amap(annot[a], a) == '[') ||
	    (type == 1 && amap(annot[a], a) == '{')) {	/* VF (AF) begins */
	    do {
		if (getann(a, &annot[a]) < 0) {
		    /* If the annotation file ends without an annotation to
		       indicate the end of VF (AF), assume that the VF (AF)
		       continues to the end of the record (setting the value
		       of f_end less than zero signals this), and return 6
		       (the maximum run length) since the VF (AF) overlaps the
		       window. */
		    f_end = -1L;
		    return (6);
		}
		am = amap(annot[a], a);
	    } while ((type == 0 && am != ']' && am != '{' && am != 'U') ||
		     (type == 1 && am != '}' && am != '[' && am != 'U'));
	    if (annot[a].time > t0) {
		/* If the episode overlaps the window, record when it ends
		   and return the maximum run length. */
		f_end = annot[a].time;
		return (6);
	    }
	}

    /* Now count consecutive (S)VEBs in the window. */
    while (annot[a].time <= t1) {
	switch(amap(annot[a], a)) {
            ...

Consider a SVEB (type=1) scenario iterating an AF episode involving the following steps:

  1. The loop has started iterating in the AF episode but is interrupted by am=='U' (unreadable) due to a localised disturbance. The time up till the shutdown is recorded in f_end and the inaf[a] is still 1 when the loop returns a SVEB run length of (6).

  2. Next time find_longest_run is called again with t0 > f_end (hence t0 is after the disturbance), the rhythm is still AF (and inaf[a] is 1), but there is no AF start marker { so the loop exits when annot[a].time >= t0 and continues below. However t1 < t0 because the run_start in the other annotation set is defined by an AF start marker (and no run_end value is set). Hence, the find_longest_run function will return a (0) length run.

The implication is that the SVEB run length is reported as six before the disturbance/shutdown and zero thereafter, throughout the length of the AF episode, even though the rhythm is still AF after the disturbance.

Of course, same goes for a VEB (type=0) scenario when iterating an VF episode.

The above described scenario is a rather common and happens in multiple MIT-BIH records.

Maybe it would be better to apply the same approach before and after the disturbance (as the fibrillation rhythm remains), so just ignore the unreadable annotations and continue when the disturbance has passed, i.e., when amap(annot[a], a) == 'C'.

Hence, the condition

if ((type == 0 && amap(annot[a], a) == '[') ||
    (type == 1 && amap(annot[a], a) == '{')) {  /* VF (AF) begins */

is extended to

if ((type == 0 && amap(annot[a], a) == '[') ||
    (type == 1 && amap(annot[a], a) == '{') ||
    (amap(annot[a], a) == 'C' && (invf[a] || inaf[a]))) {  /* VF (AF) begins or continues */

I hope that you can follow my reasoning, otherwise I may be able to provide a more detailed example.

Sincerely,
Jacob

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions