Skip to content

Commit

Permalink
gender → sex
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitriPapadopoulos committed Jun 2, 2023
1 parent cba07f5 commit 5477e90
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 52 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Additionally functionality as anonymizing, dropping or renaming channels can be
signals = np.random.rand(5, 256*300)*200 # 5 minutes of random signal
channel_names = ['ch1', 'ch2', 'ch3', 'ch4', 'ch5']
signal_headers = highlevel.make_signal_headers(channel_names, sample_frequency=256)
header = highlevel.make_header(patientname='patient_x', gender='Female')
header = highlevel.make_header(patientname='patient_x', sex='Female')
highlevel.write_edf('edf_file.edf', signals, signal_headers, header)
# read an edf file
Expand Down
2 changes: 1 addition & 1 deletion demo/readEDFFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# print("patient: %s" % f.getP);
# print("recording: %s" % f.getPatientAdditional())
print("patientcode: %s" % f.getPatientCode())
print("gender: %s" % f.getGender())
print("sex: %s" % f.getSex())
print("birthdate: %s" % f.getBirthdate())
print("patient_name: %s" % f.getPatientName())
print("patient_additional: %s" % f.getPatientAdditional())
Expand Down
17 changes: 13 additions & 4 deletions pyedflib/_extensions/_pyedflib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ __all__ = ['lib_version', 'CyEdfReader', 'set_patientcode', 'set_starttime_subse
'read_physical_samples', 'close_file', 'set_physical_maximum', 'open_file_writeonly',
'set_patient_additional', 'set_digital_maximum', 'set_birthdate', 'set_digital_minimum',
'write_digital_samples', 'set_equipment', 'set_samples_per_record','set_admincode', 'set_label',
'tell', 'rewind', 'set_gender','set_physical_dimension', 'set_transducer', 'set_prefilter',
'tell', 'rewind', 'set_sex','set_physical_dimension', 'set_transducer', 'set_prefilter',
'seek', 'set_startdatetime' ,'set_datarecord_duration', 'set_number_of_annotation_signals',
'open_errors', 'FILETYPE_EDFPLUS',
'FILETYPE_EDF','FILETYPE_BDF','FILETYPE_BDFPLUS', 'write_errors', 'get_number_of_open_files',
Expand Down Expand Up @@ -270,8 +270,13 @@ cdef class CyEdfReader:
def __get__(self):
return self.hdr.patientcode

property sex:
def __get__(self):
return self.hdr.gender

property gender:
def __get__(self):
warnings.warn('This property is deprecated.', DeprecationWarning, stacklevel=2)
return self.hdr.gender

property birthdate:
Expand Down Expand Up @@ -615,10 +620,14 @@ def rewind(handle, edfsignal):
"""void edfrewind(int handle, int edfsignal)"""
c_edf.edfrewind(handle, edfsignal)

def set_sex(handle, sex):
"""int edf_set_sex(int handle, int sex)"""
if sex is None: return 0 #don't set sex at all to prevent default 'F'
return c_edf.edf_set_gender(handle, sex)

def set_gender(handle, gender):
"""int edf_set_gender(int handle, int gender)"""
if gender is None: return 0 #don't set gender at all to prevent default 'F'
return c_edf.edf_set_gender(handle, gender)
warnings.warn('This function is deprecated.', DeprecationWarning, stacklevel=2)
set_sex(handle, gender)

def set_physical_dimension(handle, edfsignal, phys_dim):
"""int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim)"""
Expand Down
17 changes: 11 additions & 6 deletions pyedflib/edfreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ def getHeader(self):
return {"technician": self.getTechnician(), "recording_additional": self.getRecordingAdditional(),
"patientname": self.getPatientName(), "patient_additional": self.getPatientAdditional(),
"patientcode": self.getPatientCode(), "equipment": self.getEquipment(),
"admincode": self.getAdmincode(), "gender": self.getGender(), "startdate": self.getStartdatetime(),
"birthdate": self.getBirthdate()}
"admincode": self.getAdmincode(), "sex": self.getSex(), "startdate": self.getStartdatetime(),
"birthdate": self.getBirthdate(),
"gender": self.getSex()} # backwards compatibility

def getSignalHeader(self, chn):
"""
Expand Down Expand Up @@ -307,9 +308,9 @@ def getAdmincode(self):
"""
return self._convert_string(self.admincode.rstrip())

def getGender(self):
def getSex(self):
"""
Returns the Gender of the patient.
Returns the Sex of the patient.
Parameters
----------
Expand All @@ -319,12 +320,16 @@ def getGender(self):
--------
>>> import pyedflib
>>> f = pyedflib.data.test_generator()
>>> f.getGender()==''
>>> f.getSex()==''
True
>>> f.close()
"""
return self._convert_string(self.gender.rstrip())
return self._convert_string(self.sex.rstrip())

def getGender(self):
warnings.warn('This method is deprecated.', DeprecationWarning, stacklevel=2)
return self.getSex()

def getFileDuration(self):
"""
Expand Down
37 changes: 21 additions & 16 deletions pyedflib/edfwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,22 @@ def isbytestr(s):
return isinstance(s, bytes)


def gender2int(gender):
if isinstance(gender, int) or gender is None:
return gender
elif gender.lower() in ['', 'x', 'xx', 'xxx', 'unknown', '?', '??']:
def sex2int(sex):
if isinstance(sex, int) or sex is None:
return sex
elif sex.lower() in ['', 'x', 'xx', 'xxx', 'unknown', '?', '??']:
return None
elif gender.lower() in ["female", "woman", "f", "w"]:
elif sex.lower() in ["female", "woman", "f", "w"]:
return 0
elif gender.lower() in ["male", "man", "m"]:
elif sex.lower() in ["male", "man", "m"]:
return 1
else:
raise ValueError(f"Unknown gender: '{gender}'")
raise ValueError(f"Unknown sex: '{sex}'")


def gender2int(sex):
warnings.warn('This function is deprecated.', DeprecationWarning, stacklevel=2)
sex2int(sex)


class ChannelDoesNotExist(Exception):
Expand Down Expand Up @@ -195,7 +200,7 @@ def __init__(self, file_name, n_channels,
self.recording_additional = ''
self.patient_additional = ''
self.admincode = ''
self.gender = None
self.sex = None
self.recording_start_time = datetime.now().replace(microsecond=0)

self.birthdate = ''
Expand Down Expand Up @@ -228,13 +233,13 @@ def update_header(self):
"""
# some checks that warn users if header fields exceed 80 chars
patient_ident = len(self.patient_code) + len(self.patient_name) \
+ len(self.patient_additional) + 3 + 1 + 11 # 3 spaces 1 gender 11 birthdate
+ len(self.patient_additional) + 3 + 1 + 11 # 3 spaces 1 sex 11 birthdate
record_ident = len(self.equipment) + len(self.technician) \
+ len(self.admincode) + len(self.recording_additional) \
+ len('Startdate') + 3 + 11 # 3 spaces 11 birthdate

if patient_ident>80:
warnings.warn('Patient code, name, gender and birthdate combined must not be larger than 80 chars. ' +
warnings.warn('Patient code, name, sex and birthdate combined must not be larger than 80 chars. ' +
f'Currently has len of {patient_ident}. See https://www.edfplus.info/specs/edfplus.html#additionalspecs')
if record_ident>80:
warnings.warn('Equipment, technician, admincode and recording_additional combined must not be larger than 80 chars. ' +
Expand All @@ -254,7 +259,7 @@ def update_header(self):
set_patient_additional(self.handle, du(self.patient_additional))
set_equipment(self.handle, du(self.equipment))
set_admincode(self.handle, du(self.admincode))
set_gender(self.handle, gender2int(self.gender))
set_gender(self.handle, sex2int(self.sex))

set_datarecord_duration(self.handle, self.record_duration)
set_number_of_annotation_signals(self.handle, self.number_of_annotations)
Expand Down Expand Up @@ -294,7 +299,7 @@ def setHeader(self, fileHeader):
self.patient_code = fileHeader["patientcode"]
self.equipment = fileHeader["equipment"]
self.admincode = fileHeader["admincode"]
self.gender = fileHeader["gender"]
self.sex = fileHeader["sex"]
self.recording_start_time = fileHeader["startdate"]
self.birthdate = fileHeader["birthdate"]
self.update_header()
Expand Down Expand Up @@ -440,17 +445,17 @@ def setAdmincode(self, admincode):
self.admincode = admincode
self.update_header()

def setGender(self, gender):
def setSex(self, sex):
"""
Sets the gender.
Sets the sex.
This function is optional and can be called only after opening a file in writemode and before the first sample write action.
Parameters
----------
gender : int
sex : int
1 is male, 0 is female
"""
self.gender = gender2int(gender)
self.sex = sex2int(sex)
self.update_header()

def setDatarecordDuration(self, record_duration):
Expand Down
25 changes: 18 additions & 7 deletions pyedflib/highlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ def phys2dig(signal, dmin, dmax, pmin, pmax):

def make_header(technician='', recording_additional='', patientname='',
patient_additional='', patientcode= '', equipment= '',
admincode= '', gender= '', startdate=None, birthdate= ''):
admincode= '', sex= '', startdate=None, birthdate= '',
gender=None):
"""
A convenience function to create an EDF header (a dictionary) that
can be used by pyedflib to update the main header of the EDF
Expand All @@ -168,8 +169,8 @@ def make_header(technician='', recording_additional='', patientname='',
which system was used. The default is ''.
admincode : str, optional
code of the admin. The default is ''.
gender : str, optional
gender of patient. The default is ''.
sex : str, optional
sex of patient. The default is ''.
startdate : datetime.datetime, optional
startdate of recording. The default is None.
birthdate : str/datetime.datetime, optional
Expand All @@ -191,13 +192,23 @@ def make_header(technician='', recording_additional='', patientname='',
del now
if isinstance(birthdate, datetime):
birthdate = birthdate.strftime('%d %b %Y').lower()

# backwards compatibility
if gender is not None:
if sex == '':
sex = gender
elif gender != sex:
raise ValueError(f'Passed both sex and gender, with different values: "{sex}" != "{gender}"')
del gender

local = locals()

header = {}
for var in local:
if isinstance(local[var], datetime):
header[var] = local[var]
for var, value in local.items():
if isinstance(value, datetime):
header[var] = value
else:
header[var] = str(local[var])
header[var] = str(value)
return header


Expand Down
3 changes: 2 additions & 1 deletion pyedflib/tests/test_edfreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ def test_EdfReader_headerInfos(self):
np.testing.assert_equal(f.getStartdatetime(),datetimeSoll)
np.testing.assert_equal(f.getPatientCode(), 'abcxyz99')
np.testing.assert_equal(f.getPatientName(), 'Hans Muller')
np.testing.assert_equal(f.getSex(), 'Male')
np.testing.assert_equal(f.getGender(), 'Male')
np.testing.assert_equal(f.getBirthdate(), '30 jun 1969')
np.testing.assert_equal(f.getPatientAdditional(), 'patient')
Expand Down Expand Up @@ -381,7 +382,7 @@ def test_EdfReader_Legacy_Header_Info(self):
'patientcode': b'',
'equipment': b'',
'admincode': b'',
'gender': b'',
'sex': b'',
'birthdate': b''
}

Expand Down
Loading

0 comments on commit 5477e90

Please sign in to comment.