Example #1
0
def parse_events(patients,
                 event_collection,
                 event_type_names,
                 models_to_run,
                 remove_xyz_null=False,
                 remove_loc_empty=False):
    # Populates patients dic with event entries (From HFO collection)
    # Modifies patients
    for evt in event_collection:
        # Patient level
        patient_id = evt['patient_id']
        if patient_id not in patients.keys():
            # raise RuntimeWarning('The parse_electrodes may should have had the patient created first')
            patient = Patient(id=patient_id, age=parse_age(evt))
            # moment
            patients[patient.id] = patient
        else:
            patient = patients[patient_id]
            # Check consistency of patient attributes
            age = parse_age(evt)
            if age != patient.age:
                log('Warning, age should be consistent among events of the same patient'
                    )
                if patient.age != 0 or age != 0:
                    patient.age = max(age, patient.age)

        assert (patient is patients[patient_id]
                )  # They refer to the same object, but we use the short one
        # Electrode level
        e_name = parse_elec_name(evt)
        soz = parse_soz_field(evt['soz'])
        file_block = int(evt['file_block'])
        block_duration = float(evt['r_duration'])
        x, y, z = parse_coord(evt['x']), parse_coord(evt['y']), parse_coord(
            evt['z'])
        loc1, loc2, loc3, loc4, loc5 = parse_loc(evt, 1), parse_loc(
            evt, 2), parse_loc(evt, 3), parse_loc(evt, 4), parse_loc(evt, 5)

        if e_name not in patient.electrode_names():
            # raise RuntimeWarning('The parse_electrodes should have created the electrode for this event')
            # The code below would create a new a electrode from the HFO info
            electrode = Electrode(name=e_name,
                                  soz=soz,
                                  blocks={file_block: block_duration},
                                  x=x,
                                  y=y,
                                  z=z,
                                  soz_sc=parse_soz_field(evt['soz_sc']),
                                  loc1=loc1,
                                  loc2=loc2,
                                  loc3=loc3,
                                  loc4=loc4,
                                  loc5=loc5,
                                  event_type_names=event_type_names)
            patient.add_electrode(electrode)
        else:
            electrode = patient.get_electrode(e_name)
            # Check consistency

            # SOZ
            if soz != electrode.soz:
                log(msg=('Warning, soz disagreement among event and electrode'
                         'running OR between values'),
                    msg_type='elec_evt_SOZ_conflict',
                    patient=patient.id,
                    electrode=electrode.name)
            electrode.soz = electrode.soz or soz  # Fixs db bug of event nsoz and electrode.soz
            electrode.soz_sc = electrode.soz_sc or parse_soz_field(
                evt['soz_sc'])

            # File block and duration
            if file_block not in electrode.blocks.keys(
            ) or electrode.blocks[file_block] is None:
                electrode.blocks[file_block] = block_duration
            else:
                if (block_duration != electrode.blocks[file_block]):
                    raise NotImplementedError(
                        'Implement which duration must be saved if they differ.'
                    )

            # X Y Z
            if electrode.x is None:
                electrode.x = x
            if electrode.y is None:
                electrode.y = y
            if electrode.z is None:
                electrode.z = z
            if x is not None and electrode.x != x:
                raise RuntimeError(
                    'X disagreement (both not null) in event/electrode')

            ##Locations
            if electrode.loc1 == 'empty':
                electrode.loc1 = loc1
            if electrode.loc2 == 'empty':
                electrode.loc2 = loc2
            if electrode.loc3 == 'empty':
                electrode.loc3 = loc3
            if electrode.loc4 == 'empty':
                electrode.loc4 = loc4
            if electrode.loc5 == 'empty':
                electrode.loc5 = loc5

        # Elec count update
        evt_type = decode_type_name(evt['type'])
        if file_block not in electrode.evt_count[evt_type].keys():
            electrode.evt_count[evt_type][file_block] = 1
        else:
            electrode.evt_count[evt_type][file_block] += 1

        # HFO_level
        info = dict(
            x=x,
            y=y,
            z=z,
            prediction={m: []
                        for m in models_to_run},
            # for saving results of a model
            proba={m: []
                   for m in models_to_run},
            # for saving results of a model
            soz=soz,
            type=decode_type_name(evt['type']),
            file_block=int(evt['file_block']),
            start_t=float(evt['start_t']),
            finish_t=float(evt['finish_t']),
            duration=float(evt['duration']) * 1000,  # duration to milliseconds
            fr_duration=float(evt['fr_duration']),
            r_duration=float(evt['r_duration']),
            freq_av=float(evt['freq_av']),
            freq_pk=float(evt['freq_pk']),  # spikes have 0 frec and power but
            # they aren't used in ml so we just leave a None there
            power_av=None if evt['power_av'] == 0 else mt.log10(
                float(evt['power_av'])),
            power_pk=None if evt['power_pk'] == 0 else mt.log10(
                float(evt['power_pk'])),
            loc1=loc1,  # electrode.
            loc2=loc2,
            loc3=loc3,
            loc4=loc4,
            loc5=loc5,
            age=patient.age)

        if decode_type_name(evt['type']) in ['RonO', 'Fast RonO']:
            # Compass sample --> 37% has slow == [] or None, map to None
            parse_freq(info, 'slow', evt)
            parse_freq(info, 'delta', evt)
            parse_freq(info, 'theta', evt)
            parse_freq(info, 'spindle', evt)
        else:
            parse_freq(info, 'spike', evt)

        event = Event(info)
        electrode.add(event)

    # Removes electrodes with None coords or empty loc if requested by parameter
    # Notice that here elec fields are ok here after parsing events, soz has been 'or' and if a coord or loc is None/empty all their events too
    patient_ids_to_remove = set()
    for patient in patients.values():
        if remove_xyz_null:
            remove_elec_xyz_null(patient)
            if len(patient.electrodes) == 0:  # If all electrodes were removed
                patient_ids_to_remove.add(patient.id)
            check_elec_xyz_not_null(patient)
        if remove_loc_empty:
            remove_elec_loc_empty(patient)
            if len(patient.electrodes) == 0:  # If all electrodes were removed
                patient_ids_to_remove.add(patient.id)
            check_elec_loc_not_empty(patient)
    for p_name in patient_ids_to_remove:
        patients.pop(p_name)

    # Fixs EVENT inconsistencies to their electrodes
    # We know that here all electrodes have their fields ok
    evts_with_wrong_empty_loc = dict()
    for patient in patients.values():
        fix_elec_evt_soz_consistency(patient)
        fix_elec_evt_xyz_consistency(patient)
        fix_elec_evt_loc_consistency(patient, evts_with_wrong_empty_loc)

        # Just to check that the above was well done, else raise errors
        check_elec_evt_soz_consistency(patient)
        check_elec_evt_xyz_consistency(patient)
        check_elec_evt_loc_consistency(patient)
Example #2
0
def parse_electrodes(patients, elec_cursor, event_type_names):
    # Populates patients dic with electrode entries (From Electrodes collection)
    # Modifies patients
    for e in elec_cursor:
        # Patient level
        patient_id = e['patient_id']
        if patient_id not in patients.keys():
            patient = Patient(id=patient_id, age=parse_age(e))
            patients[patient_id] = patient
        else:
            patient = patients[patient_id]
            # Check consistency of patient attributes
            age = parse_age(e)
            if age != patient.age:
                log('Warning, age should agree among electrodes of the same patient'
                    )
                if patient.age != 0 or age != 0:
                    patient.age = max(age, patient.age)

        # Electrode level
        e_name = parse_elec_name(e)
        file_block = int(e['file_block'])
        x, y, z = parse_coord(e['x']), parse_coord(e['y']), parse_coord(e['z'])
        loc1, loc2, loc3, loc4, loc5 = parse_loc(e, 1), parse_loc(e, 2), \
                                       parse_loc(e, 3), parse_loc(e, 4), \
                                       parse_loc(e, 5)

        first_time_seen = e_name not in patient.electrode_names()
        if first_time_seen:
            electrode = Electrode(name=e_name,
                                  soz=parse_soz_field(e['soz']),
                                  blocks={file_block: None},
                                  x=x,
                                  y=y,
                                  z=z,
                                  soz_sc=(e['soz_sc']),
                                  loc1=loc1,
                                  loc2=loc2,
                                  loc3=loc3,
                                  loc4=loc4,
                                  loc5=loc5,
                                  event_type_names=event_type_names)
            patient.add_electrode(electrode)
        else:  # The electrode exists probably because there are many blocks for the electrodes
            electrode = patient.get_electrode(e_name)
            # Check consistency
            assert (electrode.name == e_name and patient.id == e['patient_id'])

            if parse_soz_field(e['soz']) != electrode.soz:
                log(msg=('Warning, soz disagreement among blocks of '
                         'the same patient_id, electrode, '
                         'running OR between values'),
                    msg_type='elec_blocks_SOZ_conflict',
                    patient=patient.id,
                    electrode=electrode.name)
                electrode.soz = electrode.soz or parse_soz_field(e['soz'])
            electrode.soz_sc = electrode.soz_sc or parse_soz_field(e['soz_sc'])

            if file_block not in electrode.blocks.keys():
                electrode.blocks[
                    file_block] = None  # here we will save the time of the block that is given in the HFO db...
            ##Locations
            if electrode.loc1 == 'empty':
                electrode.loc1 = loc1
            if electrode.loc2 == 'empty':
                electrode.loc2 = loc2
            if electrode.loc3 == 'empty':
                electrode.loc3 = loc3
            if electrode.loc4 == 'empty':
                electrode.loc4 = loc4
            if electrode.loc5 == 'empty':
                electrode.loc5 = loc5

            if electrode.x is None:
                electrode.x = x
            if electrode.y is None:
                electrode.y = y
            if electrode.z is None:
                electrode.z = z
            if x is not None and electrode.x != x:
                raise RuntimeError(
                    'X disagreement (both not null) in electrode blocks')

            if loc5 != 'empty' and electrode.loc5 != loc5:
                RuntimeError(
                    'This shouldnt happen, says that blocks of the same electrode have dif names none empty'
                )
                log(msg=(
                    'Warning, loc5 disagreement among blocks for the same (patient_id, electrode)'
                ),
                    msg_type='LOC5',
                    patient=patient.id,
                    electrode=electrode.name)
                if loc5 == 'Hippocampus':  # Priority
                    electrode.loc5 = loc5