Skip to content

Commit

Permalink
Merge branch 'master' into r/0.31
Browse files Browse the repository at this point in the history
  • Loading branch information
christianbrodbeck committed Dec 21, 2019
2 parents 2a2ef24 + 47b9218 commit c773ac5
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 36 deletions.
2 changes: 1 addition & 1 deletion eelbrain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@
from .fmtxt import Report


__version__ = '0.31'
__version__ = '0.31.1'
37 changes: 37 additions & 0 deletions eelbrain/_data_obj.py
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,43 @@ def __pow__(self, other):
x = self.x ** self._arg_x(other)
return Var(x, *args)

def __ipow__(self, other):
self.x **= self._arg_x(other)
return self

def __and__(self, other):
args = op_name(self, '&', other)
if isinstance(other, NDVar):
dims, x_other, x_self = other._align(self)
return NDVar(x_self & x_other, dims, *args)
return Var(self.x & self._arg_x(other), *args)

def __iand__(self, other):
self.x &= self._arg_x(other)
return self

def __xor__(self, other):
args = op_name(self, '^', other)
if isinstance(other, NDVar):
dims, x_other, x_self = other._align(self)
return NDVar(x_self ^ x_other, dims, *args)
return Var(self.x ^ self._arg_x(other), *args)

def __ixor__(self, other):
self.x ^= self._arg_x(other)
return self

def __or__(self, other):
args = op_name(self, '|', other)
if isinstance(other, NDVar):
dims, x_other, x_self = other._align(self)
return NDVar(x_self | x_other, dims, *args)
return Var(self.x | self._arg_x(other), *args)

def __ior__(self, other):
self.x |= self._arg_x(other)
return self

def __round__(self, n=0):
return Var(np.round(self.x, n), self.name, self.info)

Expand Down
13 changes: 4 additions & 9 deletions eelbrain/_experiment/preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def _load(self, subject, recording, preload):
raw.rename_channels(self.rename_channels)
if self.montage:
raw.set_montage(self.montage)
if raw.info['dig'] is None and self._dig_sessions is not None and self._dig_sessions[subject]:
if not raw.info['dig'] and self._dig_sessions is not None and self._dig_sessions[subject]:
dig_session = self._dig_sessions[subject][recording]
dig_raw = self._load(subject, dig_session, False)
raw.info['dig'] = dig_raw.info['dig']
Expand All @@ -206,19 +206,14 @@ def get_connectivity(self, data):
def get_sysname(self, info, subject, data):
if data == 'eog':
return None
elif data == 'mag':
kit_system_id = info.get('kit_system_id')
if kit_system_id:
try:
return KIT_NEIGHBORS[kit_system_id]
except KeyError:
raise NotImplementedError(f"Unknown KIT system-ID: {kit_system_id}; please contact developers")
if isinstance(self.sysname, str):
elif isinstance(self.sysname, str):
return self.sysname
elif isinstance(self.sysname, dict):
for k, v in self.sysname.items():
if fnmatch.fnmatch(subject, k):
return v
kit_system_id = info.get('kit_system_id')
return KIT_NEIGHBORS.get(kit_system_id)

def load_bad_channels(self, subject, recording):
path = self.bads_path.format(root=self.root, subject=subject, recording=recording)
Expand Down
2 changes: 1 addition & 1 deletion eelbrain/_io/fiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ def sensor_dim(info, picks=None, sysname=None, connectivity=None):
raise ValueError(f"Unknown channel unit for sysname='neuromag': {ch_unit!r}")

if connectivity is None:
connectivity = sysname
connectivity = sysname # or 'auto'

if isinstance(connectivity, str):
if connectivity in ('grid', 'none'):
Expand Down
2 changes: 1 addition & 1 deletion eelbrain/_stats/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def corr(y, x, out=None, perm=None):
if np.isscalar(out):
out = 0
else:
out.place(isnan, 0)
np.place(out, isnan, 0)
return out


Expand Down
40 changes: 30 additions & 10 deletions eelbrain/load/txt.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""
import csv
import os
from pathlib import Path
import re
from typing import Sequence, Union

Expand All @@ -26,12 +27,12 @@ def tsv(
path: str = None,
names: Union[Sequence[str], bool] = True,
types: Union[str, dict] = None,
delimiter: str = '\t',
delimiter: str = 'auto',
skiprows: int = 0,
start_tag: str = None,
ignore_missing: bool = False,
empty: str = None,
random : Union[str, Sequence[str]] = None,
random: Union[str, Sequence[str]] = None,
**fmtparams,
):
r"""Load a :class:`Dataset` from a text file.
Expand All @@ -58,7 +59,8 @@ def tsv(
``'ffvva'``) or as ``{column_name: data_type}`` dictionary (e.g.
``{'participant': 'f'}``); unspecified columns default to ``'a'``.
delimiter : str
Value delimiting cells in the input file (default: tab, ``'\t'``).
Value delimiting cells in the input file (default depends on ``path``:
``','`` if the extension is ``'.csv'``, otherwise ``'\t'``).
skiprows : int
Skip so many rows at the beginning of the file (for tsv files with
headers). Column names are expected to come after the skipped rows.
Expand Down Expand Up @@ -88,6 +90,7 @@ def tsv(
path = ui.ask_file("Load TSV", "Select tsv file to import as Dataset")
if not path:
return
path = Path(path)

if isinstance(random, str):
random = [random]
Expand All @@ -96,10 +99,17 @@ def tsv(
else:
random = list(random)

if delimiter is None: # legacy option
delimiter = ' '
fmtparams['skipinitialspace'] = True
elif delimiter == 'auto':
suffix = path.suffix.lower()
if suffix == '.csv':
delimiter = ','
else:
delimiter = '\t'

with open(path, newline='') as fid:
if delimiter is None: # legacy option
delimiter = ' '
fmtparams['skipinitialspace'] = True
reader = csv.reader(fid, delimiter=delimiter, **fmtparams)
lines = list(reader)

Expand Down Expand Up @@ -178,7 +188,19 @@ def tsv(
# convert values to data-objects
float_pattern = re.compile(FLOAT_NAN_PATTERN)
ds = _data.Dataset(name=os.path.basename(path))
np_vars = vars(np)
np_vars = {
'NA': np.nan,
'na': np.nan,
'NaN': np.nan,
'nan': np.nan,
'NAN': np.nan,
None: np.nan,
}
if empty is not None:
if empty.lower() == 'nan':
np_vars[''] = np.nan
else:
np_vars[''] = empty
bool_dict = {'True': True, 'False': False, None: False}
for name, values, type_ in zip(names, data.T, types_):
# infer type
Expand All @@ -198,9 +220,7 @@ def tsv(

# substitute values
if type_ == 'v':
if empty is not None:
values = [empty if v == '' else v for v in values]
values = [np.nan if v is None else eval(v, np_vars) for v in values]
values = [np_vars[v] if v in np_vars else int(v) if v.isdigit() else float(v) for v in values]
elif type_ == 'b':
values = [bool_dict[v] for v in values]

Expand Down
39 changes: 25 additions & 14 deletions eelbrain/tests/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from copy import deepcopy
from itertools import chain, product
from math import log
from operator import (
add, iadd, sub, isub, mul, imul, pow, ipow, truediv, itruediv, floordiv, ifloordiv, mod, imod)
import operator
import os
import pickle
import shutil
Expand Down Expand Up @@ -34,14 +33,19 @@
requires_mne_sample_data, skip_on_windows)


OPERATORS = ((add, iadd, '+'),
(sub, isub, '-'),
(mul, imul, '*'),
(mul, imul, '*'),
(pow, ipow, '**'),
(truediv, itruediv, '/'),
(floordiv, ifloordiv, '//'),
(mod, imod, '%'))
OPERATORS = {
'+': (operator.add, operator.iadd),
'-': (operator.sub, operator.isub),
'*': (operator.mul, operator.imul),
'/': (operator.truediv, operator.itruediv),
'//': (operator.floordiv, operator.ifloordiv),
'%': (operator.mod, operator.imod),
'**': (pow, operator.ipow),
'|': (operator.or_, operator.ior),
'^': (operator.xor, operator.ixor),
'&': (operator.and_, operator.iand),
}
FLOAT_OPERATORS = {k: ops for k, ops in OPERATORS.items() if k not in '|^&'}


def test_aggregate():
Expand Down Expand Up @@ -1292,13 +1296,13 @@ def test_ndvar_indexing():
u = ds[0, 'uts']
dim = Categorial('test_dim', ['a', 'b'])
v = NDVar([5, 1], dim)
for op, _, desc in OPERATORS:
for desc, (op, iop) in FLOAT_OPERATORS.items():
y = op(v, u)
assert_array_equal(y['a'], op(5, u.x))
assert_array_equal(y['b'], op(1, u.x))
# with Case from Var
case = Var([4, 1])
for op, iop, desc in OPERATORS:
for desc, (op, iop) in FLOAT_OPERATORS.items():
y = op(case, u)
assert_array_equal(y[0], op(4, u.x))
assert_array_equal(y[1], op(1, u.x))
Expand Down Expand Up @@ -1742,12 +1746,18 @@ def test_var():
# binary operations
c = 2
v2 = Var([2., 2., 3., 3.], 'w', info)
vs = [v, v2]
vsi = [v.astype(int), v2.astype(int)]
assert v.info == info
for op, iop, desc in OPERATORS:
for desc, (op, iop) in OPERATORS.items():
if desc in FLOAT_OPERATORS:
v, v2 = vs
else:
v, v2 = vsi
target = op(v.x, c)
vtarget = op(v.x, v2.x)
# op
if desc == '+':
if desc == '+': # reserved for model building
w = v.copy()
w.x = iop(w.x, c)
else:
Expand All @@ -1768,6 +1778,7 @@ def test_var():
w = v.copy()
w = iop(w, v2)
assert_array_equal(w, vtarget)
v, v2 = vs

# methods
w = abs(v)
Expand Down

0 comments on commit c773ac5

Please sign in to comment.