Open cbrnr opened 1 year ago
How to reproduce this warning? I tried with the attached sample_rate.py
without success.
https://gist.github.com/DimitriPapadopoulos/599ccc16b294d22e833e566176ed3caf
I cannot reproduce it either, I just tried on Linux. Let me try if this was specific to macOS later today, otherwise I'll close this issue.
I still get the error by running test_read_shhs()
; I forgot that I silenced this DeprecationWarning
in pyproject.toml
, so that's why I didn't see it yesterday.
So that would be test_read_shhs
, which calls read_shhs
:
def test_read_shhs(tmp_path):
"""Basic sanity checks for records read via read_shhs."""
durations = [0.1, 0.2] # hours
valid_stages = {int(s) for s in SleepStage}
_create_dummy_shhs(data_dir=tmp_path, durations=durations)
records = list(read_shhs(data_dir=tmp_path, heartbeats_source="ecg", offline=True))
assert len(records) == 4
for rec in records:
assert rec.sleep_stage_duration == 30
assert set(rec.sleep_stages) - valid_stages == set()
Function read_shhs currently calls read_raw_edf
:
rec = read_raw_edf(edf_filepath, verbose=False)
But read_raw_edf
is imported from mne.io
.
Which version of sleepecg did you use to reproduce the problem?
I'm using the dev version of SleepECG, but that should be pretty much identical to the latest release v0.5.5.
The problem is in the previous line, which calls _dummy_nsrr_edf()
, which in turn calls pyedflib.highlevel.write_edf()
(see listing in my initial comment).
If you want to reproduce this, don't forget to comment out this line first.
What's weird is that I cannot reproduce this outside of this SleepECG test, for example with this snippet:
from pyedflib.highlevel import make_signal_headers, write_edf
from scipy.datasets import electrocardiogram
ecg = electrocardiogram()
headers = make_signal_headers(["ECG"], sample_frequency=360)
write_edf("test.edf", [ecg], headers)
@hofaflo do you have any ideas? Are you seeing the DeprecationWarning
when disabling the warning filter in pyproject.toml
?
Could it depend on the version of pyedflib, with a different version used in either cases?
Perhaps the problem is here is in make_signal_header:
signal_header = {'label': label,
'dimension': dimension,
'sample_rate': sample_rate,
'sample_frequency': sample_frequency,
'physical_min': physical_min,
'physical_max': physical_max,
'digital_min': digital_min,
'digital_max': digital_max,
'transducer': transducer,
'prefilter': prefiler}
return signal_header
I guess sample_rate
shouldn't be added to the dictionary. But then I see a default value for sample_rate
and not sample_frequency
:
def make_signal_header(label, dimension='uV', sample_rate=256, sample_frequency=None,
Could it depend on the version of pyedflib, with a different version used in either cases?
I just checked, I'm using the latest version 0.1.33.
Perhaps the problem is here is in make_signal_header:
I tried popping that dict key before writing the EDF, this didn't have any effect on the warning.
Additionally, I have discovered that the documentation of pyedflib.highlevel.make_signal_header
and pyedflib.highlevel.make_signal_headers
claims that "The default is 256" for sample_rate
, instead I feel it should be None
, and that the "The default is 256" for sample_frequency
, but it is actually None
in the code.
Perhaps the problem is here is in make_signal_header:
I tried popping that dict key before writing the EDF, this didn't have any effect on the warning.
That's the first point of failure. There must be a second one, perhaps in EdfWriter.__init__
:
for i in np.arange(self.n_channels):
if self.file_type == FILETYPE_BDFPLUS or self.file_type == FILETYPE_BDF:
self.channels.append({'label': f'ch{i}', 'dimension': 'mV', 'sample_rate': 100,
'sample_frequency': None, 'physical_max': 1.0, 'physical_min': -1.0,
'digital_max': 8388607,'digital_min': -8388608,
'prefilter': '', 'transducer': ''})
elif self.file_type == FILETYPE_EDFPLUS or self.file_type == FILETYPE_EDF:
self.channels.append({'label': f'ch{i}', 'dimension': 'mV', 'sample_rate': 100,
'sample_frequency': None, 'physical_max': 1.0, 'physical_min': -1.0,
'digital_max': 32767, 'digital_min': -32768,
'prefilter': '', 'transducer': ''})
self.sample_buffer.append([])
Could you give #231 a try?
I am a bit concerned that we cannot come up with a minimal reproducible example, and that the warning only occurs in the SleepECG test...
@cbrnr I have installed sleepecg
in dev mode. Should I see the warning when running pytest
?
Yes. But make sure to disable the warning filter in pyproject.toml
(comment out that line).
Branch :make_signal_header does work for me. Commits 35e5ed773dd8f0542dafcdece288ebcd78b860d3 and 5aebc8e410a24c2a08d24df010185b6d73656900 are sufficient to fix this particular warning.
As for why you see the warning with pytest
only:
DeprecationWarning
is ignored by default:
exception DeprecationWarning
Base class for warnings about deprecated features when those warnings are intended for other Python developers.
Ignored by the default warning filters, except in the
__main__
module (PEP 565). Enabling the Python Development Mode shows this warning.
DeprecationWarning
:
By default pytest will display
DeprecationWarning
andPendingDeprecationWarning
warnings from user code and third-party libraries, as recommended by PEP 565. This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed.Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over (such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore those warnings.
But do you see the warning?
With pytest
:
I see the warning when on the master branch of my pyedflib:
I don't see the warning when on the _make_signalheader branch of my pyedflib:
Yes, I can confirm that your branch fixes the issue!
We will first need to decide how we want to handle sample_rate
. In any case, we should probably avoid warnings when reading sample_rate
except when the value is inconsistent with sample_frequency
. The question is whether we should always write sample_rate
for compatibility with older versions of the module, or not.
Any way, in the short term, you should probably ignore that warning in your tests.
IMO the problem is that even if users write an EDF and only pass sample_frequency
, they will still get the deprecation warning saying that they should not use sample_rate
. That's confusing! I suggest moving that warning up into a public function, and issue it only when users pass a sample_rate
.
Indeed, the warning should be emitted when writing and explicitly passing sample_rate
as an argument.
It should not be emitted when reading, unless of course sample_rate
and sample_frequency
are different.
The question remains whether we should write sample_rate
in addition to sample_frequency
or not.
Agreed! Just to be clear, the warning we're seeing here is emitted when writing. The question of whether or not to write sample_rate
in addition to sample_frequency
is then already solved, no? I'd write both fields, and only emit the warning if the user passes sample_rate
(which is not the case in my test since I'm passing sample_frequency
).
I am using
highlevel.write_edf()
in my tests, and even though I am passingsample_frequency
instead ofsample_rate
, I still get aDeprecationWarning
:Currently, users cannot really prevent that warning even if they have already switched to the new
sample_frequency
.