| |
- builtins.Exception(builtins.BaseException)
-
- EDFexception
- builtins.object
-
- EDFwriter
class EDFexception(builtins.Exception) |
|
Common base class for all non-exit exceptions. |
|
- Method resolution order:
- EDFexception
- builtins.Exception
- builtins.BaseException
- builtins.object
Methods defined here:
- __init__(self, message)
- Initialize self. See help(type(self)) for accurate signature.
Data descriptors defined here:
- __weakref__
- list of weak references to the object (if defined)
Methods inherited from builtins.Exception:
- __new__(*args, **kwargs) from builtins.type
- Create and return a new object. See help(type) for accurate signature.
Methods inherited from builtins.BaseException:
- __delattr__(self, name, /)
- Implement delattr(self, name).
- __getattribute__(self, name, /)
- Return getattr(self, name).
- __reduce__(...)
- helper for pickle
- __repr__(self, /)
- Return repr(self).
- __setattr__(self, name, value, /)
- Implement setattr(self, name, value).
- __setstate__(...)
- __str__(self, /)
- Return str(self).
- with_traceback(...)
- Exception.with_traceback(tb) --
set self.__traceback__ to tb and return self.
Data descriptors inherited from builtins.BaseException:
- __cause__
- exception cause
- __context__
- exception context
- __dict__
- __suppress_context__
- __traceback__
- args
|
class EDFwriter(builtins.object) |
|
A writer for EDF+ and BDF+ files.
EDF header:
offset (hex, dec) length
---------------------------------------------------------------------
0x00 0 8 ascii : version of this data format (0)
0x08 8 80 ascii : local patient identification
0x58 88 80 ascii : local recording identification
0xA8 168 8 ascii : startdate of recording (dd.mm.yy)
0xB0 176 8 ascii : starttime of recording (hh.mm.ss)
0xB8 184 8 ascii : number of bytes in header record
0xC0 192 44 ascii : reserved
0xEC 236 8 ascii : number of data records (-1 if unknown)
0xF4 244 8 ascii : duration of a data record, in seconds
0xFC 252 4 ascii : number of signals
0x00 0 ns * 16 ascii : ns * label (e.g. EEG Fpz-Cz or Body temp)
ns * 0x10 ns * 16 ns * 80 ascii : ns * transducer type (e.g. AgAgCl electrode)
ns * 0x60 ns * 96 ns * 8 ascii : ns * physical dimension (e.g. uV or degreeC)
ns * 0x68 ns * 104 ns * 8 ascii : ns * physical minimum (e.g. -500 or 34)
ns * 0x70 ns * 112 ns * 8 ascii : ns * physical maximum (e.g. 500 or 40)
ns * 0x78 ns * 120 ns * 8 ascii : ns * digital minimum (e.g. -2048)
ns * 0x80 ns * 128 ns * 8 ascii : ns * digital maximum (e.g. 2047)
ns * 0x88 ns * 136 ns * 80 ascii : ns * prefiltering (e.g. HP:0.1Hz LP:75Hz N:60)
ns * 0xD8 ns * 216 ns * 8 ascii : ns * nr of samples in each data record
ns * 0xE0 ns * 224 ns * 32 ascii : ns * reserved
ns: number of signals
All fields are left aligned and filled up with spaces, no NULL's.
Only printable ASCII characters are allowed.
Decimal separator (if any) must be a dot. No grouping characters in numbers.
For more info about the EDF and EDF+ format, visit: https://edfplus.info/specs/
For more info about the BDF and BDF+ format, visit: https://www.teuniz.net/edfbrowser/bdfplus%20format%20description.html
note: In EDF, the sensitivity (e.g. uV/bit) and offset are stored using four parameters:
digital maximum and minimum, and physical maximum and minimum.
Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV.
The sensitivity in units/bit is calculated as follows:
units per bit = (physical max - physical min) / (digital max - digital min)
The digital offset is calculated as follows:
offset = (physical max / units per bit) - digital max
For a better explanation about the relation between digital data and physical data,
read the document "Coding Schemes Used with Data Converters" (PDF):
https://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sbaa042
note: An EDF file usually contains multiple so-called datarecords. One datarecord usually has a duration of one second (this is the default but it is not mandatory!).
In that case a file with a duration of five minutes contains 300 datarecords. The duration of a datarecord can be freely chosen but, if possible, use values from
0.1 to 1 second for easier handling. Just make sure that the total size of one datarecord, expressed in bytes, does not exceed 10MByte (15MBytes for BDF(+)).
The RECOMMENDATION of a maximum datarecordsize of 61440 bytes in the EDF and EDF+ specification was useful in the time people were still using DOS as their main operating system.
Using DOS and fast (near) pointers (16-bit pointers), the maximum allocatable block of memory was 64KByte.
This is not a concern anymore so the maximum datarecord size now is limited to 10MByte for EDF(+) and 15MByte for BDF(+). This helps to accommodate for higher samplingrates
used by modern Analog to Digital Converters.
EDF header character encoding: The EDF specification says that only (printable) ASCII characters are allowed.
When writing the header info, EDFlib will assume you are using Latin1 encoding and it will automatically convert
characters with accents, umlauts, tilde, etc. to their "normal" equivalent without the accent/umlaut/tilde/etc.
in order to create a valid EDF file.
The description/name of an EDF+ annotation on the other hand, is encoded in UTF-8.
author: Teunis van Beelen |
|
Methods defined here:
- __init__(self, p_path:str, f_file_type:int, number_of_signals:int)
- Creates an instance of an EDF writer.
Path is the path to the EDF file.
Filetype must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS.
Number of signals: the number of signals that you are planning to write into the file.
- close(self) -> int
- Finalizes and closes the file.
This function is required after writing. Failing to do so will cause a corrupted and incomplete file.
Returns 0 on success, otherwise -1.
- setAdditionalPatientInfo(self, additional:str) -> int
- Sets the additional information related to the patient.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setAdditionalRecordingInfo(self, additional:str) -> int
- Sets the additional info related to the recording.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setAdministrationCode(self, admin_code:str) -> int
- Sets the administration code.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setDataRecordDuration(self, duration:int) -> int
- Sets the datarecord duration.
This function is optional, normally you don't need to change the default value of one second.
This function is NOT REQUIRED but can be called only before the first sample write action.
This function can be used when you want to use a non-integer samplerate.
For example, if you want to use a samplerate of 0.5 Hz, set the samplefrequency to 5 Hz and
the datarecord duration to 10 seconds, or alternatively, set the samplefrequency to 1 Hz and
the datarecord duration to 2 seconds.
This function can also be used when you want to use a very high samplerate.
For example, if you want to use a samplerate of 5 GHz,
set the samplefrequency to 5000 Hz and the datarecord duration to 1 microSecond.
Do not use this function if not necessary.
duration is expressed in microSeconds, range: 1 - 60000000 (1uSec. - 60 sec.)
Returns 0 on success, otherwise -1.
- setDigitalMaximum(self, s:int, dig_max:int) -> int
- Sets the maximum digital value of signal s.
Usually it's the extreme output of the ADC. The maximum value is 32767 for EDF and 8388607 for BDF.
It is the highest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.
Must be higher than digital minimum.
This function is required for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
dig_max is the maximum output value (<= 32767 for EDF and <= 8388607 for BDF).
Returns 0 on success, otherwise -1.
note: In EDF, the sensitivity (e.g. uV/bit) and offset are stored using four parameters:
digital maximum and minimum, and physical maximum and minimum.
Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV.
Usually they are the extreme input and output values of the ADC.
The sensitivity in units/bit is calculated as follows:
units per bit = (physical max - physical min) / (digital max - digital min)
The digital offset is calculated as follows:
offset = (physical max / units per bit) - digital max
- setDigitalMinimum(self, s:int, dig_min:int) -> int
- Sets the minimum digital value of signal s.
Usually it's the extreme output of the ADC. The minimum value is -32768 for EDF and -8388608 for BDF.
It is the lowest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.
Must be lower than digital maximum.
This function is required for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
dig_min is the minimum output value (>= -32768 for EDF and >= -8388608 for BDF).
Returns 0 on success, otherwise -1.
note: In EDF, the sensitivity (e.g. uV/bit) and offset are stored using four parameters:
digital maximum and minimum, and physical maximum and minimum.
Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV.
Usually they are the extreme input and output values of the ADC.
The sensitivity in units/bit is calculated as follows:
units per bit = (physical max - physical min) / (digital max - digital min)
The digital offset is calculated as follows:
offset = (physical max / units per bit) - digital max
- setEquipment(self, equipment:str) -> int
- Sets the description of the equipment used for the recording.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setNumberOfAnnotationSignals(self, annot_signals:int) -> int
- Sets the number of annotation signals.
The default value is 1.
This function is optional and, if used, must be called before the first sample write action.
Normally you don't need to change the default value. Only when the number of annotations
you want to write is higher than the number of datarecords in the recording, you can use
this function to increase the storage space for annotations.
- setPatientBirthDate(self, year:int, month:int, day:int) -> int
- Sets the patients' birthdate.
This function is optional and can be called only before the first sample write action.
year: 1800 - 3000
month: 1 - 12
day: 1 - 31
Returns 0 on success, otherwise -1.
- setPatientCode(self, code:str) -> int
- Sets the patientcode.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setPatientGender(self, gender:int) -> int
- Sets the patient's gender.
gender: 0 = female, 1 = male, 2 = unknown or not applicable (default)
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setPatientName(self, name:str) -> int
- Sets the patientname.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setPhysicalDimension(self, s:int, physical_dimension:str) -> int
- Sets the physical_dimension (unit) of signal s.
("uV", "BPM", "mA", "Degr.", etc.) String must contain printable ASCII only.
This function recommended for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
physical_dimension is the physical dimension description.
Returns 0 on success, otherwise -1.
- setPhysicalMaximum(self, s:int, phys_max:float) -> int
- Sets the maximum physical value of signal s.
This is the value of the input of the ADC when the output equals the value of "digital maximum".
It is the highest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.
Must be un-equal to physical minimum.
This function is required for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
phys_max is the maximum input value.
Returns 0 on success, otherwise -1.
note: In EDF, the sensitivity (e.g. uV/bit) and offset are stored using four parameters:
digital maximum and minimum, and physical maximum and minimum.
Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV.
Usually they are the extreme input and output values of the ADC.
The sensitivity in units/bit is calculated as follows:
units per bit = (physical max - physical min) / (digital max - digital min)
The digital offset is calculated as follows:
offset = (physical max / units per bit) - digital max
- setPhysicalMinimum(self, s:int, phys_min:float) -> int
- Sets the minimum physical value of signal s.
This is the value of the input of the ADC when the output equals the value of "digital minimum".
It is the lowest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.
Must be un-equal to physical maximum.
This function is required for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
phys_min is the minimum input value.
Returns 0 on success, otherwise -1.
note: In EDF, the sensitivity (e.g. uV/bit) and offset are stored using four parameters:
digital maximum and minimum, and physical maximum and minimum.
Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV.
Usually they are the extreme input and output values of the ADC.
The sensitivity in units/bit is calculated as follows:
units per bit = (physical max - physical min) / (digital max - digital min)
The digital offset is calculated as follows:
offset = (physical max / units per bit) - digital max
- setPreFilter(self, s:int, prefilter:str) -> int
- Sets the prefilter description of signal s.
(e.g. "HP:0.05Hz", "LP:250Hz", "N:60Hz", etc.) String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
s is the signal number (zero-based).
prefilter is the prefilter description.
Returns 0 on success, otherwise -1.
- setSampleFrequency(self, s:int, sf:int) -> int
- Sets the samplefrequency of signal s.
(In reallity, it sets the number of samples in a datarecord.)
The samplefrequency of a signal is determined as: sf = number of samples in a datarecord / datarecord duration.
The samplefrequency equals the number of samples in a datarecord only when the datarecord duration is set to the default of one second.
This function is required for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
sf is the samplefrequency.
Returns 0 on success, otherwise -1.
- setSignalLabel(self, s:int, label:str) -> int
- Sets the label (name) of signal s.
(e.g. "FP1", "SaO2", etc.) String must contain printable ASCII only.
This function is recommended for every signal and can be called only before the first sample write action.
s is the signal number (zero-based).
label is the signallabel.
Returns 0 on success, otherwise -1.
- setStartDateTime(self, year:int, month:int, day:int, hour:int, minute:int, second:int, subsecond:int) -> int
- Sets the startdate and starttime.
If not called, the system date and time at runtime will be used.
This function is optional and can be called only before the first sample write action.
If subsecond precision is not needed or not applicable, leave it at zero.
Note: for anonymization purposes, the consensus is to use 1985-01-01 00:00:00 for the startdate and starttime.
year: 1985 - 2084
month: 1 - 12
day: 1 - 31
hour: 0 - 23
minute: 0 - 59
second: 0 - 59
subsecond: 0 - 9999 expressed in units of 100 microSeconds
Returns 0 on success, otherwise -1.
- setTechnician(self, technician:str) -> int
- Sets the name or id of the technician who performed the recording.
String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
Returns 0 on success, otherwise -1.
- setTransducer(self, s:int, transducer:str) -> int
- Sets the transducer description of signal s.
("AgAgCl cup electrodes", etc.) String must contain printable ASCII only.
This function is optional and can be called only before the first sample write action.
s is the signal number (zero-based).
transducer is the transducer description.
Returns 0 on success, otherwise -1.
- version(self) -> int
- If version is 1.00 then it will return 100.
- writeAnnotation(self, onset:int, duration:int, description:str) -> int
- Writes an annotation/event to the file.
onset is relative to the starttime of the recording and must be >= 0.
onset and duration are in units of 100 microSeconds. Resolution is 0.0001 second.
E.g. 34.071 seconds must be written as 340710.
If duration is unknown or not applicable: set a negative number (-1).
Description is a string containing the text that describes the event.
This function is optional.
- writeSamples(self, buf:<built-in function array>) -> int
- Write samples.
Writes sf samples into the file.
Buf must be a one-dimensional numpy array containing samples of one signal of datatype int32, float_ or float64.
For EDF, dataype int16 can also be used.
If buf is of type integer, the samples are written into the file without any conversion.
If buf is of type float, the physical samples will be converted to digital samples using the
values of physical maximum, physical minimum, digital maximum and digital minimum.
The number of samples written is equal to the samplefrequency of the signal.
(actually, it's the value that is set with setSampleFrequency()).
Size of buf should be equal to or bigger than the samplefrequency.
Call this function for every signal in the file. The order is important!
When there are 4 signals in the file, the order of calling this function
must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc.
The end of a recording must always be at the end of a complete cycle.
buf is a one-dimensional numpy array of datatype int32, float_ or float64. For EDF, dataype int16 can also be used.
Returns 0 on success, otherwise -1.
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
Data and other attributes defined here:
- EDFLIB_DATARECORD_SIZE_TOO_BIG = -26
- EDFLIB_DIGMAX_LOWER_THAN_DIGMIN = -24
- EDFLIB_DIGMIN_IS_DIGMAX = -23
- EDFLIB_DO_NOT_READ_ANNOTATIONS = 0
- EDFLIB_FILETYPE_BDF = 2
- EDFLIB_FILETYPE_BDFPLUS = 3
- EDFLIB_FILETYPE_EDF = 0
- EDFLIB_FILETYPE_EDFPLUS = 1
- EDFLIB_FILETYPE_ERROR = -7
- EDFLIB_FILE_ALREADY_OPENED = -6
- EDFLIB_FILE_CLOSED = -13
- EDFLIB_FILE_CONTAINS_FORMAT_ERRORS = -3
- EDFLIB_FILE_IS_DISCONTINUOUS = -10
- EDFLIB_FILE_READ_ERROR = -5
- EDFLIB_FILE_WRITE_ERROR = -8
- EDFLIB_INVALID_ARGUMENT = -12
- EDFLIB_INVALID_READ_ANNOTS_VALUE = -11
- EDFLIB_MALLOC_ERROR = -1
- EDFLIB_MAXFILES_REACHED = -4
- EDFLIB_MAXSIGNALS = 640
- EDFLIB_MAX_ANNOTATION_LEN = 512
- EDFLIB_NO_SAMPLES_IN_RECORD = -22
- EDFLIB_NO_SIGNALS = -20
- EDFLIB_NO_SUCH_FILE_OR_DIRECTORY = -2
- EDFLIB_NUMBER_OF_SIGNALS_INVALID = -9
- EDFLIB_PHYSMIN_IS_PHYSMAX = -25
- EDFLIB_READ_ALL_ANNOTATIONS = 2
- EDFLIB_READ_ANNOTATIONS = 1
- EDFLIB_TIME_DIMENSION = 10000000
- EDFLIB_TOO_MANY_SIGNALS = -21
- EDFLIB_VERSION = 108
- EDFSEEK_CUR = 1
- EDFSEEK_END = 2
- EDFSEEK_SET = 0
| |