def create_synthetic_eeghdf_file(): U, D, s2u, of = gen_synthetic_signal(fs=10, duration_sec=2) hf = eeghdf.EEGHDFWriter(hdf_file_name='synthetic.eeg.h5', fileattr='w') hf.write_patient_info('test, subject', patientcode='0000000', gender='unknown', birthdate_isostring='2018-01-01T12:00') T = 2 nchan = 5 fs = 10 labels = [str(ii) for ii in range(nchan)] U, D, s2u, dig_offsets = gen_synthetic_signal() print('D:', D) dig_maxs = D.max(axis=1) dig_mins = D.min(axis=1) phys_maxs = U.max(axis=1) phys_mins = U.min(axis=1) phys_units = ['s', 'uV', 'uV', 'uV', 'uV'] record = hf.create_record_block(record_duration_seconds=T, start_isodatetime='2018-01-01T13:00.00', end_isodatetime='2018-01-01T13:00.02', number_channels=nchan, num_samples_per_channel=fs * T, sample_frequency=fs, signal_labels=labels, signal_physical_maxs=phys_maxs, signal_physical_mins=phys_mins, signal_digital_mins=dig_mins, signal_digital_maxs=dig_maxs, physical_dimensions=phys_units, patient_age_days=1 / 24) # need to create edf_annotations hf.write_annotations_b([], record=record) signals = hf.hdf['record-0']['signals'] signals[:] = D return {'hf': hf, 'U': U, 'D': D, 's2u': s2u, 'offsets': of}
def edf2hdf(fn, outfn='', anonymize=False, verbose=False): """ convert an edf file @fn to hdf5 using fairly straightforward mapping if no @outfn is specified, then use the same name as the @fn but change extention to "eeg.h5" return True if successful """ if not outfn: base = os.path.basename(fn) base, ext = os.path.splitext(base) # outfn = os.path.join(hdf_dir, base) outfn = base + '.eeg.h5' # all the data point related stuff with edflib.EdfReader(fn) as ef: # read all EDF+ header information in just the way I want it header = { 'file_name': os.path.basename(fn), 'filetype': ef.filetype, 'patient_name': ef.patient_name, 'patientcode': ef.patientcode, 'gender': ef.gender, 'signals_in_file': ef.signals_in_file, 'datarecords_in_file': ef.datarecords_in_file, 'file_duration_100ns': ef.file_duration_100ns, 'file_duration_seconds': ef.file_duration_seconds, 'startdate_date': datetime.date(ef.startdate_year, ef.startdate_month, ef.startdate_day), 'start_datetime': datetime.datetime(ef.startdate_year, ef.startdate_month, ef.startdate_day, ef.starttime_hour, ef.starttime_minute, ef.starttime_second), 'starttime_subsecond_offset': ef.starttime_subsecond, 'birthdate_date': ef.birthdate_date, 'patient_additional': ef.patient_additional, 'admincode': ef.admincode, # usually the study eg. C13-100 'technician': ef.technician, 'equipment': ef.equipment, 'recording_additional': ef.recording_additional, 'datarecord_duration_100ns': ef.datarecord_duration_100ns, } if verbose: pprint.pprint(header) debug = print else: def nulfunction(*args,**kwargs): return None debug = nulfunction # use arrow start_datetime = header['start_datetime'] # end_date_time = datetime.datetime(ef.enddate_year, ef.enddate_month, ef.enddate_day, ef.endtime_hour, # ef.endtime_minute, ef.endtime_second) # tz naive # end_date_time - start_date_time duration = datetime.timedelta(seconds=header['file_duration_seconds']) # derived information birthdate = header['birthdate_date'] if birthdate: age = arrow.get(start_datetime) - arrow.get(header['birthdate_date']) debug('predicted age: %s' % age) # total_seconds() returns a float debug('predicted age (seconds): %s' % age.total_seconds()) else: age = datetime.timedelta(seconds=0) birthdate = '' if anonymize: raise Exception('not implemented') # anonymized version if necessary header['end_datetime'] = header['start_datetime'] + duration ############# signal array information ################## # signal block related stuff nsigs = ef.signals_in_file # again know/assume that this is uniform sampling across signals # for each record block fs0 = ef.samplefrequency(0) signal_frequency_array = ef.get_signal_freqs() # print("signal_frequency_array::\n", repr(signal_frequency_array)) assert all(signal_frequency_array == fs0) nsamples0 = ef.samples_in_file(0) # samples per channel debug('nsigs=%s, fs0=%s, nsamples0=%s\n' % (nsigs, fs0, nsamples0)) num_samples_per_signal = ef.get_samples_per_signal() # np array # print("num_samples_per_signal::\n", repr(num_samples_per_signal), '\n') assert all(num_samples_per_signal == nsamples0) file_duration_sec = ef.file_duration_seconds #print("file_duration_sec", repr(file_duration_sec)) # Note that all annotations except the top row must also specify a duration. # long long onset; /* onset time of the event, expressed in units of 100 # nanoSeconds and relative to the starttime in the header */ # char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ # char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the # event in UTF-8, this is a null term string of max length 512*/ # start("x.y"), end, char[20] # annotations = ef.read_annotations_as_array() # get numpy array of # annotations annotations_b = ef.read_annotations_b_100ns_units() # print("annotations_b::\n") # pprint.pprint(annotations_b) # get list of annotations signal_text_labels = ef.get_signal_text_labels() debug("signal_text_labels::\n") if verbose: pprint.pprint(signal_text_labels) # ef.recording_additional # print() signal_digital_mins = np.array( [ef.digital_min(ch) for ch in range(nsigs)]) signal_digital_total_min = min(signal_digital_mins) #print("digital mins:", repr(signal_digital_mins)) #print("digital total min:", repr(signal_digital_total_min)) signal_digital_maxs = np.array( [ef.digital_max(ch) for ch in range(nsigs)]) signal_digital_total_max = max(signal_digital_maxs) #print("digital maxs:", repr(signal_digital_maxs)) #print("digital total max:", repr(signal_digital_total_max)) signal_physical_dims = [ ef.physical_dimension(ch) for ch in range(nsigs)] # print('signal_physical_dims::\n') # pprint.pprint(signal_physical_dims) #print() signal_physical_maxs = np.array( [ef.physical_max(ch) for ch in range(nsigs)]) #print('signal_physical_maxs::\n', repr(signal_physical_maxs)) signal_physical_mins = np.array( [ef.physical_min(ch) for ch in range(nsigs)]) #print('signal_physical_mins::\n', repr(signal_physical_mins)) # this don't seem to be used much so I will put at end signal_prefilters = [ef.prefilter(ch).strip() for ch in range(nsigs)] #print('signal_prefilters::\n') # pprint.pprint(signal_prefilters) #print() signal_transducers = [ef.transducer(ch).strip() for ch in range(nsigs)] #print('signal_transducers::\n') #pprint.pprint(signal_transducers) with eeghdf.EEGHDFWriter(outfn, 'w') as eegf: if header['birthdate_date']: birthdate_isostring = header['birthdate_date'].strftime('%Y-%m-%d') else: birthdate_isostring = '' eegf.write_patient_info(patient_name=header['patient_name'], patientcode=header['patientcode'], gender=header['gender'], birthdate_isostring=birthdate_isostring, # gestational_age_at_birth_days # born_premature patient_additional=header['patient_additional']) rec = eegf.create_record_block(record_duration_seconds=header['file_duration_seconds'], start_isodatetime=str(header['start_datetime']), end_isodatetime=str(header['end_datetime']), number_channels=header['signals_in_file'], num_samples_per_channel=nsamples0, sample_frequency=fs0, signal_labels=signal_text_labels, signal_physical_mins=signal_physical_mins, signal_physical_maxs=signal_physical_maxs, signal_digital_mins=signal_digital_mins, signal_digital_maxs=signal_digital_maxs, physical_dimensions=signal_physical_dims, patient_age_days=age.total_seconds() / 86400.0, signal_prefilters=signal_prefilters, signal_transducers=signal_transducers, technician=header['technician']) eegf.write_annotations_b(annotations_b) # may be should be called record annotations edfblock_itr = edf_block_iter_generator( ef, nsamples0, 100 * ef.samples_in_datarecord(0)*header['signals_in_file'], # samples_per_chunk roughly 100 datarecords at a time dtype='int32') signals = eegf.stream_dig_signal_to_record_block(rec, edfblock_itr) return True # we succeeded
def edf2hdf(fn, outfn="", hdf_dir="", anonymize=False): """ convert an edf file to hdf5 using fairly straightforward mapping return True if successful by default (if outfn and hdf_dir are not set) the output is put in the same directory as the input file you can also specify the output file (full path) by setting outfn directly or simple specify a different target directory by specifying @hdf_dir as a directory path @database_sourcel_label tells us which database it came from LPCH_NK or STANFORD_NK this is important! """ if not outfn: parentdir = os.path.dirname(fn) base = os.path.basename(fn) base, ext = os.path.splitext(base) base = base + DEFAULT_EXT if hdf_dir: outfn = os.path.join(hdf_dir, base) else: outfn = os.path.join(parentdir, base) # debug('outfn:', outfn) # all the data point related stuff with edflib.EdfReader(fn) as ef: # read all EDF+ header information in just the way I want it header = { "file_name": os.path.basename(fn), "filetype": ef.filetype, "patient_name": ef.patient_name, "patientcode": ef.patientcode, "studyadmincode": ef.admincode, "gender": ef.gender, "signals_in_file": ef.signals_in_file, "datarecords_in_file": ef.datarecords_in_file, "file_duration_100ns": ef.file_duration_100ns, "file_duration_seconds": ef.file_duration_seconds, "startdate_date": datetime.date(ef.startdate_year, ef.startdate_month, ef.startdate_day), "start_datetime": datetime.datetime( ef.startdate_year, ef.startdate_month, ef.startdate_day, ef.starttime_hour, ef.starttime_minute, ef.starttime_second, ), "starttime_subsecond_offset": ef.starttime_subsecond, "birthdate_date": ef.birthdate_date, # str "patient_additional": ef.patient_additional, # str "admincode": ef.admincode, # usually the study eg. C13-100 "technician": ef.technician, "equipment": ef.equipment, "recording_additional": ef.recording_additional, "datarecord_duration_100ns": ef.datarecord_duration_100ns, } # defbug debug("original header") debug(pprint.pformat(header)) # use arrow start_datetime = header["start_datetime"] duration = datetime.timedelta(seconds=header["file_duration_seconds"]) # derived information birthdate = header["birthdate_date"] if birthdate: age = arrow.get(start_datetime) - arrow.get( header["birthdate_date"]) debug("predicted age: %s" % age) # total_seconds() returns a float debug("predicted age (seconds): %s" % age.total_seconds()) else: age = datetime.timedelta(seconds=0) if anonymize: anonymous_header = create_simple_anonymous_header(header) header = anonymous_header header["end_datetime"] = header["start_datetime"] + duration ############# signal array information ################## # signal block related stuff nsigs = ef.signals_in_file # again know/assume that this is uniform sampling across signals fs0 = ef.samplefrequency(0) signal_frequency_array = ef.get_signal_freqs() dfs = np.diff(signal_frequency_array) dfs_ind = np.where(dfs != 0.0) dfs_ind = dfs_ind[0] last_ind = 0 for dd in dfs_ind + 1: debug("block:", signal_frequency_array[last_ind:dd]) last_ind = dd debug("last block:", signal_frequency_array[last_ind:]) debug("where does sampling rate change?", np.where(dfs != 0.0)) debug("elements:", signal_frequency_array[np.where(dfs != 0.0)]) debug("signal_frequency_array::\n", repr(signal_frequency_array)) debug("len(signal_frequency_array):", len(signal_frequency_array)) assert all(signal_frequency_array[:-3] == fs0) nsamples0 = ef.samples_in_file(0) # samples per channel debug("nsigs=%s, fs0=%s, nsamples0=%s\n" % (nsigs, fs0, nsamples0)) num_samples_per_signal = ef.get_samples_per_signal() # np array debug("num_samples_per_signal::\n", repr(num_samples_per_signal), "\n") # assert all(num_samples_per_signal == nsamples0) file_duration_sec = ef.file_duration_seconds # debug("file_duration_sec", repr(file_duration_sec)) # Note that all annotations except the top row must also specify a duration. # long long onset; /* onset time of the event, expressed in units of 100 # nanoSeconds and relative to the starttime in the header */ # char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ # char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the # event in UTF-8, this is a null term string of max length 512*/ # start("x.y"), end, char[20] # annotations = ef.read_annotations_as_array() # get numpy array of # annotations annotations_b = ef.read_annotations_b_100ns_units() # debug("annotations_b::\n") # pprint.pprint(annotations_b) # get list of annotations signal_text_labels = ef.get_signal_text_labels() debug("signal_text_labels::\n") debug(pprint.pformat(signal_text_labels)) debug("normalized text labels::\n") signal_text_labels_lpch_normalized = [ normalize_lpch_signal_label(label) for label in signal_text_labels ] debug(pprint.pformat(signal_text_labels_lpch_normalized)) # ef.recording_additional # debug() signal_digital_mins = np.array( [ef.digital_min(ch) for ch in range(nsigs)]) signal_digital_total_min = min(signal_digital_mins) debug("digital mins:", repr(signal_digital_mins)) debug("digital total min:", repr(signal_digital_total_min)) signal_digital_maxs = np.array( [ef.digital_max(ch) for ch in range(nsigs)]) signal_digital_total_max = max(signal_digital_maxs) debug("digital maxs:", repr(signal_digital_maxs)) # debug("digital total max:", repr(signal_digital_total_max)) signal_physical_dims = [ ef.physical_dimension(ch) for ch in range(nsigs) ] # debug('signal_physical_dims::\n') # pprint.pformat(signal_physical_dims) # debug() signal_physical_maxs = np.array( [ef.physical_max(ch) for ch in range(nsigs)]) # debug('signal_physical_maxs::\n', repr(signal_physical_maxs)) signal_physical_mins = np.array( [ef.physical_min(ch) for ch in range(nsigs)]) # debug('signal_physical_mins::\n', repr(signal_physical_mins)) # this don't seem to be used much so I will put at end signal_prefilters = [ef.prefilter(ch).strip() for ch in range(nsigs)] # debug('signal_prefilters::\n') # pprint.pformat(signal_prefilters) # debug() signal_transducers = [ef.transducer(ch).strip() for ch in range(nsigs)] # debug('signal_transducers::\n') # pprint.pformat(signal_transducers) with eeghdf.EEGHDFWriter(outfn, "w") as eegf: eegf.write_patient_info( patient_name=header["patient_name"], patientcode=header["patientcode"], gender=header["gender"], birthdate_isostring=str(header["birthdate_date"]), # gestational_age_at_birth_days # born_premature patient_additional=header["patient_additional"], ) signal_text_labels_lpch_normalized = [ normalize_lpch_signal_label(label) for label in signal_text_labels ] rec = eegf.create_record_block( record_duration_seconds=header["file_duration_seconds"], start_isodatetime=str(header["start_datetime"]), end_isodatetime=str(header["end_datetime"]), number_channels=header["signals_in_file"], num_samples_per_channel=nsamples0, sample_frequency=fs0, signal_labels=signal_text_labels_lpch_normalized, signal_physical_mins=signal_physical_mins, signal_physical_maxs=signal_physical_maxs, signal_digital_mins=signal_digital_mins, signal_digital_maxs=signal_digital_maxs, physical_dimensions=signal_physical_dims, patient_age_days=age.total_seconds() / 86400.0, signal_prefilters=signal_prefilters, signal_transducers=signal_transducers, technician=header["technician"], studyadmincode=header["studyadmincode"], ) eegf.write_annotations_b( annotations_b) # may be should be called record annotations edfblock_itr = edf_block_iter_generator( ef, nsamples0, 100 * ef.samples_in_datarecord(0) * header[ "signals_in_file"], # samples_per_chunk roughly 100 datarecords at a time dtype="int32", ) signals = eegf.stream_dig_signal_to_record_block(rec, edfblock_itr) return True
def edf2hdf2(fn, outfn='', hdf_dir='', anonymize=False): """ convert an edf file to hdf5 using fairly straightforward mapping return True if successful @database_sourcel_label tells us which database it came from LPCH_NK or STANFORD_NK this is important! """ if not outfn: dir_name = os.path.dirname(fn) if not hdf_dir: hdf_dir = dir_name base = os.path.basename(fn) base, ext = os.path.splitext(base) base = base + '.eeg.h5' outfn = os.path.join(hdf_dir, base) # print('outfn:', outfn) # all the data point related stuff with edflib.EdfReader(fn) as ef: # read all EDF+ header information in just the way I want it header = { 'file_name': os.path.basename(fn), 'filetype': ef.filetype, 'patient_name': ef.patient_name, 'patientcode': ef.patientcode, 'studyadmincode': ef.admincode, 'gender': ef.gender, 'signals_in_file': ef.signals_in_file, 'datarecords_in_file': ef.datarecords_in_file, 'file_duration_100ns': ef.file_duration_100ns, 'file_duration_seconds': ef.file_duration_seconds, 'startdate_date': datetime.date(ef.startdate_year, ef.startdate_month, ef.startdate_day), 'start_datetime': datetime.datetime(ef.startdate_year, ef.startdate_month, ef.startdate_day, ef.starttime_hour, ef.starttime_minute, ef.starttime_second), 'starttime_subsecond_offset': ef.starttime_subsecond, 'birthdate_date': ef.birthdate_date, 'patient_additional': ef.patient_additional, 'admincode': ef.admincode, # usually the study eg. C13-100 'technician': ef.technician, 'equipment': ef.equipment, 'recording_additional': ef.recording_additional, 'datarecord_duration_100ns': ef.datarecord_duration_100ns, } pprint.pprint(header) #### validation code ##### validator = None # if source_database_label=='LPCH_NK': # validator = ValidateTrackHeaderLPCH(header=header) # elif source_database_label== 'STANFORD_NK': # validator = ValidateTrackHeaderStanford(header=header) # else: # raise ValidationError # if not validator.is_valid(): # print('problem with this file:', fn) # print(validator.errors,validator.error_code, # validator.error_params) # return False, validator # else: # print('\nvalid header::') # pprint.pprint(validator.cleaned_data) # header = validator.cleaned_data # from here on the header is valid and cleaned # use arrow start_datetime = header['start_datetime'] # end_date_time = datetime.datetime(ef.enddate_year, ef.enddate_month, ef.enddate_day, ef.endtime_hour, # ef.endtime_minute, ef.endtime_second) # tz naive # end_date_time - start_date_time duration = datetime.timedelta(seconds=header['file_duration_seconds']) # derived information birthdate = header['birthdate_date'] if birthdate: age = arrow.get(start_datetime) - arrow.get( header['birthdate_date']) debug('predicted age: %s' % age) # total_seconds() returns a float debug('predicted age (seconds): %s' % age.total_seconds()) else: age = datetime.timedelta(seconds=0) # if anonymize: # if source_database_label== 'LPCH_NK': # anonymizer = AnonymizeTrackHeaderLPCH(header, source_database_label=source_database_label) # if source_database_label == 'STANFORD_NK': # anonymizer = AnonymizeTrackHeaderStanford(header, source_database_label=source_database_label) # header = anonymizer.anonymous_header # replace the original header with the anonymous one # print('anonymized header') # pprint.pprint(header) # anonymized version if necessary header['end_datetime'] = header['start_datetime'] + duration ############# signal array information ################## # signal block related stuff nsigs = ef.signals_in_file # again know/assume that this is uniform sampling across signals fs0 = ef.samplefrequency(0) signal_frequency_array = ef.get_signal_freqs() dfs = np.diff(signal_frequency_array) dfs_ind = np.where(dfs != 0.0) dfs_ind = dfs_ind[0] last_ind = 0 for dd in dfs_ind + 1: print("block:", signal_frequency_array[last_ind:dd]) last_ind = dd print("last block:", signal_frequency_array[last_ind:]) print("where does sampling rate change?", np.where(dfs != 0.0)) print("elements:", signal_frequency_array[np.where(dfs != 0.0)]) print("signal_frequency_array::\n", repr(signal_frequency_array)) print("len(signal_frequency_array):", len(signal_frequency_array)) assert all(signal_frequency_array[:-3] == fs0) nsamples0 = ef.samples_in_file(0) # samples per channel print('nsigs=%s, fs0=%s, nsamples0=%s\n' % (nsigs, fs0, nsamples0)) num_samples_per_signal = ef.get_samples_per_signal() # np array print("num_samples_per_signal::\n", repr(num_samples_per_signal), '\n') # assert all(num_samples_per_signal == nsamples0) file_duration_sec = ef.file_duration_seconds #print("file_duration_sec", repr(file_duration_sec)) # Note that all annotations except the top row must also specify a duration. # long long onset; /* onset time of the event, expressed in units of 100 # nanoSeconds and relative to the starttime in the header */ # char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ # char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the # event in UTF-8, this is a null term string of max length 512*/ # start("x.y"), end, char[20] # annotations = ef.read_annotations_as_array() # get numpy array of # annotations annotations_b = ef.read_annotations_b_100ns_units() # print("annotations_b::\n") # pprint.pprint(annotations_b) # get list of annotations signal_text_labels = ef.get_signal_text_labels() print("signal_text_labels::\n") pprint.pprint(signal_text_labels) print("normalized text labels::\n") signal_text_labels_lpch_normalized = [ normalize_lpch_signal_label(label) for label in signal_text_labels ] pprint.pprint(signal_text_labels_lpch_normalized) # ef.recording_additional # print() signal_digital_mins = np.array( [ef.digital_min(ch) for ch in range(nsigs)]) signal_digital_total_min = min(signal_digital_mins) print("digital mins:", repr(signal_digital_mins)) print("digital total min:", repr(signal_digital_total_min)) signal_digital_maxs = np.array( [ef.digital_max(ch) for ch in range(nsigs)]) signal_digital_total_max = max(signal_digital_maxs) print("digital maxs:", repr(signal_digital_maxs)) #print("digital total max:", repr(signal_digital_total_max)) signal_physical_dims = [ ef.physical_dimension(ch) for ch in range(nsigs) ] # print('signal_physical_dims::\n') # pprint.pprint(signal_physical_dims) #print() signal_physical_maxs = np.array( [ef.physical_max(ch) for ch in range(nsigs)]) #print('signal_physical_maxs::\n', repr(signal_physical_maxs)) signal_physical_mins = np.array( [ef.physical_min(ch) for ch in range(nsigs)]) #print('signal_physical_mins::\n', repr(signal_physical_mins)) # this don't seem to be used much so I will put at end signal_prefilters = [ef.prefilter(ch).strip() for ch in range(nsigs)] #print('signal_prefilters::\n') # pprint.pprint(signal_prefilters) #print() signal_transducers = [ef.transducer(ch).strip() for ch in range(nsigs)] #print('signal_transducers::\n') #pprint.pprint(signal_transducers) if not header[ 'patient_name']: # iassume is "EDF" file so need to split patient info try: s = ef.patient print('local subject:', s) patientcode, gender, dob, name, age_str = s.split( ) # the age_str seems illegal per edfplus print("try this:") header['patient_name'] = name header['birthdate_date'] = dob header['gender'] = gender header['patient_additional'] = age_str header['patientcode'] = patientcode except: pass try: s = ef.patient ss = s.split() if len(ss) > 0: header['patient_name'] = ss[0] header['patient_additional'] = s except: pass with eeghdf.EEGHDFWriter(outfn, 'w') as eegf: eegf.write_patient_info( patient_name=header['patient_name'], patientcode=header['patientcode'], gender=header['gender'], birthdate_isostring=header['birthdate_date'], # gestational_age_at_birth_days # born_premature patient_additional=header['patient_additional']) signal_text_labels_lpch_normalized = [ normalize_lpch_signal_label(label) for label in signal_text_labels ] rec = eegf.create_record_block( record_duration_seconds=header['file_duration_seconds'], start_isodatetime=str(header['start_datetime']), end_isodatetime=str(header['end_datetime']), number_channels=header['signals_in_file'], num_samples_per_channel=nsamples0, sample_frequency=fs0, signal_labels=signal_text_labels_lpch_normalized, signal_physical_mins=signal_physical_mins, signal_physical_maxs=signal_physical_maxs, signal_digital_mins=signal_digital_mins, signal_digital_maxs=signal_digital_maxs, physical_dimensions=signal_physical_dims, patient_age_days=age.total_seconds() / 86400.0, signal_prefilters=signal_prefilters, signal_transducers=signal_transducers, technician=header['technician'], studyadmincode=header['studyadmincode']) eegf.write_annotations_b( annotations_b) # may be should be called record annotations edfblock_itr = edf_block_iter_generator( ef, nsamples0, 100 * ef.samples_in_datarecord(0) * header[ 'signals_in_file'], # samples_per_chunk roughly 100 datarecords at a time dtype='int32') signals = eegf.stream_dig_signal_to_record_block(rec, edfblock_itr) return True, validator # we succeeded