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)
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