示例#1
0
### Observation procedure ###
#############################
def _rhythmblock_obs_proc(pattern):
    """Observation procedure executed once the rhythm pattern has finished"""
    # We asign the endpoint of the hypothesis.
    pattern.hypothesis.end.value = pattern.evidence[o.QRS][-1].time.value


RHYTHMBLOCK_PATTERN = PatternAutomata()
RHYTHMBLOCK_PATTERN.name = 'Rhythm Block'
RHYTHMBLOCK_PATTERN.Hypothesis = o.RhythmBlock
RHYTHMBLOCK_PATTERN.add_transition(0, 1, o.Cardiac_Rhythm, ENVIRONMENT,
                                   _prev_rhythm_tconst, _prev_rhythm_gconst)
RHYTHMBLOCK_PATTERN.add_transition(0, 2, o.Cardiac_Rhythm, ENVIRONMENT,
                                   _prev_rhythm_tconst, _prev_asyst_gconst)
RHYTHMBLOCK_PATTERN.add_transition(1, 2, o.QRS, ENVIRONMENT, _qrs1_tconst)
RHYTHMBLOCK_PATTERN.add_transition(2, 3, o.QRS, ENVIRONMENT, _qrs2_tconst)
RHYTHMBLOCK_PATTERN.add_transition(3, 4, o.QRS, ABSTRACTED, _qrs3_tconst,
                                   _qrs_gconst)
RHYTHMBLOCK_PATTERN.add_transition(4, 5, o.PWave, ABSTRACTED, _p_qrs_tconst)
RHYTHMBLOCK_PATTERN.add_transition(4, 6, o.TWave, ABSTRACTED, _t_qrs_tconst)
RHYTHMBLOCK_PATTERN.add_transition(4, 6)
RHYTHMBLOCK_PATTERN.add_transition(5, 6, o.TWave, ABSTRACTED, _t_qrs_tconst)
RHYTHMBLOCK_PATTERN.add_transition(6, 4, o.QRS, ABSTRACTED, _qrsn_tconst,
                                   _qrs_gconst)
RHYTHMBLOCK_PATTERN.final_states.add(6)
RHYTHMBLOCK_PATTERN.abstractions[o.QRS] = (
    RHYTHMBLOCK_PATTERN.transitions[4], )
RHYTHMBLOCK_PATTERN.obs_proc = _rhythmblock_obs_proc
RHYTHMBLOCK_PATTERN.freeze()
def create_regular_rhythm(name, hypothesis, rr_bounds):
    """
    Creates a new abstraction pattern automata with the properties of a regular
    rhythm, but allows to parameterize the RR limits, the hypothesis observable
    type and the name of the pattern.
    """
    # The hypothesis must be a cardiac rhythm.
    assert issubclass(hypothesis, o.Cardiac_Rhythm)

    def _pair_gconst(pattern, _):
        """
        General constraints to be satisfied when a regular rhythm consists
        of only two beats.
        """
        if pattern.evidence[o.Cardiac_Rhythm]:
            _check_missed_beats(pattern)
            prhythm = pattern.evidence[o.Cardiac_Rhythm][0]
            rhythm = pattern.hypothesis
            # Previous rhythm cannot be a regular rhythm.
            verify(not isinstance(prhythm, o.RegularCardiacRhythm))
            mrr, stdrr = prhythm.meas.rr
            beats = pattern.evidence[o.QRS]
            rr = beats[-1].time.start - beats[0].time.start
            verify(rr in rr_bounds)
            # Avoid duplicate hypotheses with overlapping rhythms.
            if pattern.automata is SINUS_PATTERN:
                verify(C.TACHY_RR.end < rr < C.BRADY_RR.start)
            maxvar = max(C.TMARGIN, min(C.RR_MAX_DIFF, 2.5 * stdrr))
            verify(rr in Iv(mrr - maxvar, mrr + maxvar))
            # Besides being in rhythm, the two beats must share the morphology.
            verify(signal_match(beats[0].shape, beats[1].shape))
            # The amplitude difference is also constrained
            for lead in beats[0].shape:
                if lead in beats[1].shape:
                    samp, qamp = (beats[0].shape[lead].amplitude,
                                  beats[1].shape[lead].amplitude)
                    verify(
                        min(samp, qamp) /
                        max(samp, qamp) >= C.MISSED_QRS_MAX_DIFF)
            rhythm.meas = o.CycleMeasurements(
                (rr, stdrr), (prhythm.meas.rt[0], C.QT_ERR_STD),
                (prhythm.meas.pq[0], C.QT_ERR_STD))

    _qrs_tconst = _get_qrs_tconst(rr_bounds)
    # Automata definition
    automata = PatternAutomata()
    automata.name = name
    automata.Hypothesis = hypothesis
    automata.add_transition(0, 1, o.Cardiac_Rhythm, ENVIRONMENT,
                            _prev_rhythm_tconst, _prev_rhythm_gconst)
    automata.add_transition(1, 2, o.QRS, ENVIRONMENT, _qrs_tconst)
    automata.add_transition(2, 3, o.QRS, ABSTRACTED, _qrs_tconst)
    automata.add_transition(2, 9, o.QRS, ABSTRACTED, _qrs_tconst, _pair_gconst)
    automata.add_transition(3, 4, o.PWave, ABSTRACTED, _p_qrs_tconst)
    automata.add_transition(3, 5, o.TWave, ABSTRACTED, _t_qrs_tconst)
    automata.add_transition(3, 8, o.QRS, ABSTRACTED, _qrs_tconst,
                            _cycle_finished_gconst)
    automata.add_transition(4, 5, o.TWave, ABSTRACTED, _t_qrs_tconst)
    automata.add_transition(5, 6, o.QRS, ABSTRACTED, _qrs_tconst)
    automata.add_transition(5, 8, o.QRS, ABSTRACTED, _qrs_tconst,
                            _cycle_finished_gconst)
    automata.add_transition(6, 7, o.PWave, ABSTRACTED, _p_qrs_tconst)
    automata.add_transition(6, 8, o.TWave, ABSTRACTED, _t_qrs_tconst,
                            _cycle_finished_gconst)
    automata.add_transition(7, 8, o.TWave, ABSTRACTED, _t_qrs_tconst,
                            _cycle_finished_gconst)
    automata.add_transition(8, 6, o.QRS, ABSTRACTED, _qrs_tconst)
    automata.add_transition(8, 8, o.QRS, ABSTRACTED, _qrs_tconst,
                            _cycle_finished_gconst)
    automata.add_transition(9, 10, o.PWave, ABSTRACTED, _p_qrs_tconst)
    automata.add_transition(9, 11, o.TWave, ABSTRACTED, _t_qrs_tconst)
    automata.add_transition(9, 11)
    automata.add_transition(10, 11, o.TWave, ABSTRACTED, _t_qrs_tconst)
    automata.final_states.add(8)
    automata.final_states.add(11)
    automata.abstractions[o.QRS] = (automata.transitions[2],
                                    automata.transitions[3])
    automata.obs_proc = _rhythm_obs_proc
    automata.freeze()
    return automata
示例#3
0
TRIGEMINY_PATTERN.add_transition(11, 13, o.TWave, ABS, get_t_tconst(3))
TRIGEMINY_PATTERN.add_transition(11, 13)
TRIGEMINY_PATTERN.add_transition(12, 13, o.TWave, ABS, get_t_tconst(-3))
#
TRIGEMINY_PATTERN.add_transition(13, 14, o.PWave, ABS, get_p_tconst(-2))
TRIGEMINY_PATTERN.add_transition(13, 15, o.TWave, ABS, get_t_tconst(-2))
TRIGEMINY_PATTERN.add_transition(13, 15)
TRIGEMINY_PATTERN.add_transition(14, 15, o.TWave, ABS, get_t_tconst(-2))
#
TRIGEMINY_PATTERN.add_transition(15, 16, o.PWave, ABS, get_p_tconst(-1))
TRIGEMINY_PATTERN.add_transition(15, 17, o.TWave, ABS, get_t_tconst(-1))
TRIGEMINY_PATTERN.add_transition(15, 17)
TRIGEMINY_PATTERN.add_transition(16, 17, o.TWave, ABS, get_t_tconst(-1))
# Each new cycle adds three more QRS complexes.
# N
TRIGEMINY_PATTERN.add_transition(17, 18, o.QRS, ABS, _reg_nae_tconst)
# V
TRIGEMINY_PATTERN.add_transition(18, 19, o.QRS, ABS, _ect_qrs_tconst)
# N
TRIGEMINY_PATTERN.add_transition(19, 20, o.QRS, ABS, _reg_ae_tconst,
                                 _cycle_finished_gconst)
# And the corresponding P and T waves.
TRIGEMINY_PATTERN.add_transition(20, 12, o.PWave, ABS, get_p_tconst(-3))
TRIGEMINY_PATTERN.add_transition(20, 13, o.TWave, ABS, get_t_tconst(-3))
TRIGEMINY_PATTERN.add_transition(20, 13)
#
TRIGEMINY_PATTERN.final_states.add(17)
TRIGEMINY_PATTERN.abstractions[o.QRS] = (TRIGEMINY_PATTERN.transitions[2], )
TRIGEMINY_PATTERN.obs_proc = _rhythm_obs_proc
TRIGEMINY_PATTERN.freeze()
示例#4
0
# T waves are searched after the necessary QRS have been observed.
ST = 9 + C.AFIB_MIN_NQRS - 4
for i in range(C.AFIB_MIN_NQRS - 2):
    AFIB_PATTERN.add_transition(ST, ST + 1, o.TWave, ABSTRACTED,
                                get_t_tconst(i + 1))
    AFIB_PATTERN.add_transition(ST, ST + 1)
    ST += 1
# T wave for the last observed QRS, and cycle QRS observation.
AFIB_PATTERN.add_transition(ST, ST + 1, o.TWave, ABSTRACTED, get_t_tconst(-1))
AFIB_PATTERN.add_transition(ST, ST + 1)
AFIB_PATTERN.add_transition(ST + 1, ST, o.QRS, ABSTRACTED, _qrs_tconst,
                            _qrs_gconst)
AFIB_PATTERN.final_states.add(8)
AFIB_PATTERN.final_states.add(ST + 1)
AFIB_PATTERN.abstractions[o.QRS] = (AFIB_PATTERN.transitions[5], )
AFIB_PATTERN.obs_proc = _rhythm_obs_proc
AFIB_PATTERN.freeze()

#########################
### Helper structures ###
#########################

# The following polynomial gives us the minimum number of Non-Empty Cells in
# the RdR plot to positively detect atrial fibrillation, as described in
# "Lian: A simple method to detect Atrial Fibrillation using RR intervals"

_NEC = scipy.interpolate.interpolate.lagrange([32, 64, 128], [23, 40, 65])

if __name__ == "__main__":
    pass