Skip to content

Commit

Permalink
DOC: Better documentation of realign_raw (mne-tools#12135)
Browse files Browse the repository at this point in the history
  • Loading branch information
larsoner authored Oct 26, 2023
1 parent 58e8c7e commit debc275
Show file tree
Hide file tree
Showing 13 changed files with 60 additions and 27 deletions.
3 changes: 2 additions & 1 deletion mne/epochs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4062,12 +4062,13 @@ def _concatenate_epochs(
event_id = deepcopy(out.event_id)
selection = out.selection
# offset is the last epoch + tmax + 10 second
shift = int((10 + tmax) * out.info["sfreq"])
shift = np.int64((10 + tmax) * out.info["sfreq"])
# Allow reading empty epochs (ToDo: Maybe not anymore in the future)
if out._allow_empty:
events_offset = 0
else:
events_offset = int(np.max(events[0][:, 0])) + shift
events_offset = np.int64(events_offset)
events_overflow = False
warned = False
for ii, epochs in enumerate(epochs_list[1:], 1):
Expand Down
12 changes: 9 additions & 3 deletions mne/io/bti/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ def read_int8(fid):

def read_uint16(fid):
"""Read unsigned 16bit integer from bti file."""
return _unpack_simple(fid, ">u2", np.uint16)
return _unpack_simple(fid, ">u2", np.uint32)


def read_int16(fid):
"""Read 16bit integer from bti file."""
return _unpack_simple(fid, ">i2", np.int16)
return _unpack_simple(fid, ">i2", np.int32)


def read_uint32(fid):
Expand Down Expand Up @@ -88,7 +88,13 @@ def read_double(fid):

def read_int16_matrix(fid, rows, cols):
"""Read 16bit integer matrix from bti file."""
return _unpack_matrix(fid, rows, cols, dtype=">i2", out_dtype=np.int16)
return _unpack_matrix(
fid,
rows,
cols,
dtype=">i2",
out_dtype=np.int32,
)


def read_float_matrix(fid, rows, cols):
Expand Down
17 changes: 16 additions & 1 deletion mne/io/ctf/res4.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def _read_ustring(fid, n_bytes):

def _read_int2(fid):
"""Read int from short."""
return np.fromfile(fid, ">i2", 1)[0]
return _auto_cast(np.fromfile(fid, ">i2", 1)[0])


def _read_int(fid):
Expand Down Expand Up @@ -208,6 +208,9 @@ def _read_res4(dsdir):
coil["area"] *= 1e-4
# convert to dict
chs = [dict(zip(chs.dtype.names, x)) for x in chs]
for ch in chs:
for key, val in ch.items():
ch[key] = _auto_cast(val)
res["chs"] = chs
for k in range(res["nchan"]):
res["chs"][k]["ch_name"] = res["ch_names"][k]
Expand All @@ -216,3 +219,15 @@ def _read_res4(dsdir):
_read_comp_coeff(fid, res)
logger.info(" res4 data read.")
return res


def _auto_cast(x):
# Upcast scalars
if isinstance(x, np.ScalarType):
if x.dtype.kind == "i":
if x.dtype != np.int64:
x = x.astype(np.int64)
elif x.dtype.kind == "f":
if x.dtype != np.float64:
x = x.astype(np.float64)
return x
6 changes: 3 additions & 3 deletions mne/io/edf/edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ def _read_gdf_header(fname, exclude, include=None):
"Header information is incorrect for record length. "
"Default record length set to 1."
)
nchan = np.fromfile(fid, UINT32, 1)[0]
nchan = int(np.fromfile(fid, UINT32, 1)[0])
channels = list(range(nchan))
ch_names = [_edf_str(fid.read(16)).strip() for ch in channels]
exclude = _find_exclude_idx(ch_names, exclude, include)
Expand Down Expand Up @@ -1177,7 +1177,7 @@ def _read_gdf_header(fname, exclude, include=None):
fid.seek(etp)
etmode = np.fromfile(fid, UINT8, 1)[0]
if etmode in (1, 3):
sr = np.fromfile(fid, UINT8, 3)
sr = np.fromfile(fid, UINT8, 3).astype(np.uint32)
event_sr = sr[0]
for i in range(1, len(sr)):
event_sr = event_sr + sr[i] * 2 ** (i * 8)
Expand Down Expand Up @@ -1297,7 +1297,7 @@ def _read_gdf_header(fname, exclude, include=None):
"Default record length set to 1."
)

nchan = np.fromfile(fid, UINT16, 1)[0]
nchan = int(np.fromfile(fid, UINT16, 1)[0])
fid.seek(2, 1) # 2bytes reserved

# Channels (variable header)
Expand Down
6 changes: 3 additions & 3 deletions mne/io/egi/egi.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def _read_header(fid):
)

def my_fread(*x, **y):
return np.fromfile(*x, **y)[0]
return int(np.fromfile(*x, **y)[0])

info = dict(
version=version,
Expand Down Expand Up @@ -57,8 +57,8 @@ def my_fread(*x, **y):
dict(
n_categories=0,
n_segments=1,
n_samples=np.fromfile(fid, ">i4", 1)[0],
n_events=np.fromfile(fid, ">i2", 1)[0],
n_samples=int(np.fromfile(fid, ">i4", 1)[0]),
n_events=int(np.fromfile(fid, ">i2", 1)[0]),
event_codes=[],
category_names=[],
category_lengths=[],
Expand Down
2 changes: 1 addition & 1 deletion mne/io/egi/egimff.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def _read_mff_header(filepath):
# by what we need to (e.g., a sample rate of 500 means we can multiply
# by 1 and divide by 2 rather than multiplying by 500 and dividing by
# 1000)
numerator = signal_blocks["sfreq"]
numerator = int(signal_blocks["sfreq"])
denominator = 1000
this_gcd = math.gcd(numerator, denominator)
numerator = numerator // this_gcd
Expand Down
8 changes: 4 additions & 4 deletions mne/io/nihon/nihon.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def _read_nihon_header(fname):
t_datablock["address"] = t_data_address

fid.seek(t_data_address + 0x26)
t_n_channels = np.fromfile(fid, np.uint8, 1)[0]
t_n_channels = np.fromfile(fid, np.uint8, 1)[0].astype(np.int64)
t_datablock["n_channels"] = t_n_channels

t_channels = []
Expand All @@ -219,14 +219,14 @@ def _read_nihon_header(fname):
t_datablock["channels"] = t_channels

fid.seek(t_data_address + 0x1C)
t_record_duration = np.fromfile(fid, np.uint32, 1)[0]
t_record_duration = np.fromfile(fid, np.uint32, 1)[0].astype(np.int64)
t_datablock["duration"] = t_record_duration

fid.seek(t_data_address + 0x1A)
sfreq = np.fromfile(fid, np.uint16, 1)[0] & 0x3FFF
t_datablock["sfreq"] = sfreq
t_datablock["sfreq"] = sfreq.astype(np.int64)

t_datablock["n_samples"] = int(t_record_duration * sfreq / 10)
t_datablock["n_samples"] = np.int64(t_record_duration * sfreq // 10)
t_controlblock["datablocks"].append(t_datablock)
controlblocks.append(t_controlblock)
header["controlblocks"] = controlblocks
Expand Down
2 changes: 1 addition & 1 deletion mne/io/nsx/nsx.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def _get_hdr_info(fname, stim_channel=True, eog=None, misc=None):

stim_channel_idxs, _ = _check_stim_channel(stim_channel, ch_names)

nchan = nsx_info["channel_count"]
nchan = int(nsx_info["channel_count"])
logger.info("Setting channel info structure...")
chs = list()
pick_mask = np.ones(len(ch_names))
Expand Down
13 changes: 7 additions & 6 deletions mne/preprocessing/realign.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ def realign_raw(raw, other, t_raw, t_other, verbose=None):
The second raw instance. It will be resampled to match ``raw``.
t_raw : array-like, shape (n_events,)
The times of shared events in ``raw`` relative to ``raw.times[0]`` (0).
Typically these could be events on some TTL channel like
``find_events(raw)[:, 0] - raw.first_samp``.
Typically these could be events on some TTL channel such as::
find_events(raw)[:, 0] / raw.info["sfreq"] - raw.first_time
t_other : array-like, shape (n_events,)
The times of shared events in ``other`` relative to ``other.times[0]``.
%(verbose)s
Expand Down Expand Up @@ -92,11 +93,11 @@ def realign_raw(raw, other, t_raw, t_other, verbose=None):
logger.info(f"Cropping {zero_ord:0.3f} s from the start of raw")
raw.crop(zero_ord, None)
t_raw -= zero_ord
else: # need to crop start of other to match raw
t_crop = zero_ord / first_ord
elif zero_ord < 0: # need to crop start of other to match raw
t_crop = -zero_ord / first_ord
logger.info(f"Cropping {t_crop:0.3f} s from the start of other")
other.crop(-t_crop, None)
t_other += t_crop
other.crop(t_crop, None)
t_other -= t_crop

# 3. Resample data using the first-order term
nan_ch_names = [
Expand Down
2 changes: 2 additions & 0 deletions mne/report/tests/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,8 @@ def test_survive_pickle(tmp_path):
def test_manual_report_2d(tmp_path, invisible_fig):
"""Simulate user manually creating report by adding one file at a time."""
pytest.importorskip("sklearn")
pytest.importorskip("pandas")

from sklearn.exceptions import ConvergenceWarning

r = Report(title="My Report")
Expand Down
2 changes: 1 addition & 1 deletion mne/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ def _call_old(self, rr, n_jobs):

def _fread3(fobj):
"""Read 3 bytes and adjust."""
b1, b2, b3 = np.fromfile(fobj, ">u1", 3)
b1, b2, b3 = np.fromfile(fobj, ">u1", 3).astype(np.int64)
return (b1 << 16) + (b2 << 8) + b3


Expand Down
3 changes: 2 additions & 1 deletion tools/azure_dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ elif [ "${TEST_MODE}" == "pip-pre" ]; then
python -m pip install $STD_ARGS pip setuptools wheel packaging setuptools_scm
python -m pip install $STD_ARGS --only-binary ":all:" --extra-index-url "https://www.riverbankcomputing.com/pypi/simple" PyQt6 PyQt6-sip PyQt6-Qt6
echo "Numpy etc."
python -m pip install $STD_ARGS --only-binary ":all:" --extra-index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" "numpy>=2.0.0.dev0" "scipy>=1.12.0.dev0" statsmodels pandas scikit-learn matplotlib
# As of 2023/10/25 no pandas (or statsmodels) because they pin to NumPy < 2
python -m pip install $STD_ARGS --only-binary ":all:" --extra-index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" "numpy>=2.0.0.dev0" "scipy>=1.12.0.dev0" scikit-learn matplotlib
echo "dipy"
python -m pip install $STD_ARGS --only-binary ":all:" --extra-index-url "https://pypi.anaconda.org/scipy-wheels-nightly/simple" dipy
echo "h5py"
Expand Down
11 changes: 9 additions & 2 deletions tools/github_actions_dependencies.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash -ef

set -o pipefail

STD_ARGS="--progress-bar off --upgrade"
if [ ! -z "$CONDA_ENV" ]; then
echo "Uninstalling MNE for CONDA_ENV=${CONDA_ENV}"
Expand All @@ -18,7 +20,8 @@ else
echo "PyQt6"
pip install $STD_ARGS --only-binary ":all:" --default-timeout=60 --extra-index-url https://www.riverbankcomputing.com/pypi/simple PyQt6
echo "NumPy/SciPy/pandas etc."
pip install $STD_ARGS --only-binary ":all:" --default-timeout=60 --extra-index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" "numpy>=2.0.0.dev0" scipy scikit-learn pandas matplotlib pillow statsmodels
# As of 2023/10/25 no pandas (or statsmodels, nilearn) because they pin to NumPy < 2
pip install $STD_ARGS --only-binary ":all:" --default-timeout=60 --extra-index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" "numpy>=2.0.0.dev0" scipy scikit-learn matplotlib pillow
echo "dipy"
pip install $STD_ARGS --only-binary ":all:" --default-timeout=60 --extra-index-url "https://pypi.anaconda.org/scipy-wheels-nightly/simple" dipy
echo "H5py"
Expand All @@ -27,7 +30,8 @@ else
pip install $STD_ARGS --only-binary ":all:" --extra-index-url "https://test.pypi.org/simple" openmeeg
# No Numba because it forces an old NumPy version
echo "nilearn and openmeeg"
pip install $STD_ARGS git+https://github.com/nilearn/nilearn
# pip install $STD_ARGS git+https://github.com/nilearn/nilearn
pip install $STD_ARGS openmeeg
echo "VTK"
pip install $STD_ARGS --only-binary ":all:" --extra-index-url "https://wheels.vtk.org" vtk
python -c "import vtk"
Expand All @@ -45,9 +49,12 @@ else
pip install $STD_ARGS git+https://github.com/joblib/joblib@master
echo "EDFlib-Python"
pip install $STD_ARGS git+https://gitlab.com/Teuniz/EDFlib-Python@master
# Until Pandas is fixed, make sure we didn't install it
! python -c "import pandas"
fi
echo ""


# for compat_minimal and compat_old, we don't want to --upgrade
if [ ! -z "$CONDA_DEPENDENCIES" ]; then
echo "Installing dependencies for conda"
Expand Down

0 comments on commit debc275

Please sign in to comment.