Skip to content

Commit

Permalink
Improve support of different encoding formats (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mathieu Scheltienne authored Dec 16, 2024
1 parent 0277cb5 commit 8ee5e10
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 49 deletions.
65 changes: 41 additions & 24 deletions src/antio/libeep/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def get_channel_count(self) -> int:
return pyeep.get_channel_count(self._handle)

def get_channel(
self, index: int, encoding: str = "latin-1"
self, index: int, *, encoding: str
) -> tuple[str, str, str, str, str]:
"""Get the channel information at a given index.
Expand All @@ -56,7 +56,7 @@ def get_channel(
index : int
Index of the channel.
encoding : str
Encoding used for the unit string.
Encoding used for the strings.
Returns
-------
Expand All @@ -75,15 +75,18 @@ def get_channel(
raise RuntimeError(
f"Channel index {index} exceeds total channel count {n_channels}."
)
unit = pyeep.get_channel_unit(self._handle, index)
unit = unit.decode(encoding) if unit is not None else ""
return (
pyeep.get_channel_label(self._handle, index),
unit,
pyeep.get_channel_reference(self._handle, index),
pyeep.get_channel_status(self._handle, index),
pyeep.get_channel_type(self._handle, index),
functions = (
pyeep.get_channel_label,
pyeep.get_channel_unit,
pyeep.get_channel_reference,
pyeep.get_channel_status,
pyeep.get_channel_type,
)
channel = []
for func in functions:
value = func(self._handle, index)
channel.append(value.decode(encoding) if value is not None else "")
return tuple(channel)

def get_sample_frequency(self) -> int:
"""Get the sampling frequency of the recording in Hz.
Expand Down Expand Up @@ -199,17 +202,20 @@ def get_start_time_and_fraction(self) -> Optional[datetime]:
start_date = np.round(start_date * 3600.0 * 24.0) - 2209161600
return datetime.fromtimestamp(start_date + start_fraction, timezone.utc)

def get_hospital(self) -> str:
def get_hospital(self, *, encoding: str) -> str:
"""Get hospital name of the recording.
Returns
-------
hospital : str
Hospital name.
encoding : str
Encoding used for the string.
"""
return pyeep.get_hospital(self._handle)
hospital = pyeep.get_hospital(self._handle)
return hospital.decode(encoding) if hospital is not None else ""

def get_machine_info(self) -> tuple[str, str, str]:
def get_machine_info(self, *, encoding: str) -> tuple[str, str, str]:
"""Get machine information.
Returns
Expand All @@ -219,14 +225,21 @@ def get_machine_info(self) -> tuple[str, str, str]:
- 0: machine make
- 1: machine model
- 2: machine serial number
encoding : str
Encoding used for the strings.
"""
return (
pyeep.get_machine_make(self._handle),
pyeep.get_machine_model(self._handle),
pyeep.get_machine_serial_number(self._handle),
functions = (
pyeep.get_machine_make,
pyeep.get_machine_model,
pyeep.get_machine_serial_number,
)
info = []
for func in functions:
value = func(self._handle)
info.append(value.decode(encoding) if value is not None else "")
return tuple(info)

def get_patient_info(self) -> tuple[str, str, str, date | None]:
def get_patient_info(self, *, encoding: str) -> tuple[str, str, str, date | None]:
"""Get patient info.
Returns
Expand All @@ -237,14 +250,18 @@ def get_patient_info(self) -> tuple[str, str, str, date | None]:
- 1: patient id
- 2: patient sex
- 3: patient date of birth
encoding : str
Encoding used for the strings.
"""
functions = (pyeep.get_patient_name, pyeep.get_patient_id)
info = []
for func in functions:
value = func(self._handle)
info.append(value.decode(encoding) if value is not None else "")
sex = pyeep.get_patient_sex(self._handle)
return (
pyeep.get_patient_name(self._handle),
pyeep.get_patient_id(self._handle),
"" if sex == "\x00" else sex,
self._get_date_of_birth(),
)
info.append("" if sex == "\x00" else sex)
info.append(self._get_date_of_birth())
return tuple(info)

def _get_date_of_birth(self) -> date:
"""Get date of birth of the patient.
Expand Down
27 changes: 20 additions & 7 deletions src/antio/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


def read_info(
cnt: InputCNT,
cnt: InputCNT, *, encoding: str = "latin-1"
) -> tuple[list[str], list[str], list[str], list[str], list[str]]:
"""Parse the channel information from the cnt file.
Expand All @@ -37,10 +37,13 @@ def read_info(
ch_types : list of str
List of channel types.
.. versionadded: 0.3.0.
encoding : str
Encoding used for the strings.
.. versionadded: 0.5.0
"""
ch_names, ch_units, ch_refs, ch_status, ch_types = [], [], [], [], []
for k in range(cnt.get_channel_count()):
channel = cnt.get_channel(k)
channel = cnt.get_channel(k, encoding=encoding)
ch_names.append(channel[0])
ch_units.append(channel[1].lower()) # always lower the unit for mapping
ch_refs.append(channel[2])
Expand All @@ -49,7 +52,9 @@ def read_info(
return ch_names, ch_units, ch_refs, ch_status, ch_types


def read_subject_info(cnt: InputCNT) -> tuple[str, str, int, date]:
def read_subject_info(
cnt: InputCNT, *, encoding: str = "latin-1"
) -> tuple[str, str, int, date]:
"""Parse the subject information from the cnt file.
Parameters
Expand All @@ -67,17 +72,22 @@ def read_subject_info(cnt: InputCNT) -> tuple[str, str, int, date]:
Subject sex (0=unknown, 1=male, 2=female).
birthday : datetime.date | None
The subject birthday. None if it could not be parsed.
encoding : str
Encoding used for the strings.
.. versionadded: 0.5.0
Notes
-----
.. versionadded: 0.3.0.
"""
name, his_id, sex, birthday = cnt.get_patient_info()
name, his_id, sex, birthday = cnt.get_patient_info(encoding=encoding)
sex = {"": 0, "M": 1, "F": 2}.get(sex, 0)
return his_id, name, sex, birthday


def read_device_info(cnt: InputCNT) -> tuple[str, str, str, str]:
def read_device_info(
cnt: InputCNT, *, encoding: str = "latin-1"
) -> tuple[str, str, str, str]:
"""Parse the machine information from the cnt file.
Parameters
Expand All @@ -95,13 +105,16 @@ def read_device_info(cnt: InputCNT) -> tuple[str, str, str, str]:
Device serial.
site : str
Device site.
encoding : str
Encoding used for the strings.
.. versionadded: 0.5.0
Notes
-----
.. versionadded: 0.3.0.
"""
make, mode, serial = cnt.get_machine_info()
site = cnt.get_hospital()
make, mode, serial = cnt.get_machine_info(encoding=encoding)
site = cnt.get_hospital(encoding=encoding)
return make, mode, serial, site


Expand Down
69 changes: 60 additions & 9 deletions src/libeep/python/pyeep.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,12 @@ pyeep_get_channel_label(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_channel_label(handle, index));
const char* label_str = libeep_get_channel_label(handle, index);
if (label_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", label_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand All @@ -103,7 +108,12 @@ pyeep_get_channel_status(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_channel_status(handle, index));
const char* status_str = libeep_get_channel_status(handle, index);
if (status_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", status_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand All @@ -115,8 +125,12 @@ pyeep_get_channel_type(PyObject* self, PyObject* args) {
if(!PyArg_ParseTuple(args, "ii", & handle, & index)) {
return NULL;
}
const char* type_str = libeep_get_channel_type(handle, index);
if (type_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("s", libeep_get_channel_type(handle, index));
return Py_BuildValue("y", type_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand Down Expand Up @@ -147,7 +161,12 @@ pyeep_get_channel_reference(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_channel_reference(handle, index));
const char* ref_str = libeep_get_channel_reference(handle, index);
if (ref_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", ref_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand Down Expand Up @@ -320,7 +339,12 @@ pyeep_get_hospital(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_hospital(handle));
const char* hospital_str = libeep_get_hospital(handle);
if (hospital_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", hospital_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand All @@ -332,7 +356,12 @@ pyeep_get_machine_make(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_machine_make(handle));
const char* mmake_str = libeep_get_machine_make(handle);
if (mmake_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", mmake_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand All @@ -344,7 +373,12 @@ pyeep_get_machine_model(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_machine_model(handle));
const char* model_str = libeep_get_machine_model(handle);
if (model_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", model_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand All @@ -356,7 +390,12 @@ pyeep_get_machine_serial_number(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_machine_serial_number(handle));
const char* sn_str = libeep_get_machine_serial_number(handle);
if (sn_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", sn_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand All @@ -368,6 +407,13 @@ pyeep_get_patient_id(PyObject* self, PyObject* args) {
return NULL;
}

const char* patient_id_str = libeep_get_patient_id(handle);
if (patient_id_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", patient_id_str);

return Py_BuildValue("s", libeep_get_patient_id(handle));
}
///////////////////////////////////////////////////////////////////////////////
Expand All @@ -380,7 +426,12 @@ pyeep_get_patient_name(PyObject* self, PyObject* args) {
return NULL;
}

return Py_BuildValue("s", libeep_get_patient_name(handle));
const char* patient_str = libeep_get_patient_name(handle);
if (patient_str == NULL) {
Py_RETURN_NONE;
}

return Py_BuildValue("y", patient_str);
}
///////////////////////////////////////////////////////////////////////////////
static
Expand Down
Loading

0 comments on commit 8ee5e10

Please sign in to comment.