def test_contains_row_different_types(): """Test that _contains_row() can handle different dtypes without warning. This is to check if we're successfully avoiding a FutureWarning emitted by NumPy, see https://github.com/mne-tools/mne-bids/pull/372 (pytest must be configured to fail on warnings for this to work!) """ data = odict(age=[20, 30, 40, 'n/a']) # string row = dict(age=60) # int _contains_row(data, row)
def test_tsv_handler(tmp_path): """Test the TSV handling.""" # create some dummy data d = odict(a=[1, 2, 3, 4], b=['five', 'six', 'seven', 'eight']) assert _contains_row(d, {'a': 1, 'b': 'five'}) d2 = odict(a=[5], b=['nine']) d = _combine_rows(d, d2) assert 5 in d['a'] d2 = odict(a=[5]) d = _combine_rows(d, d2) assert 'n/a' in d['b'] d2 = odict(a=[5], b=['ten']) d = _combine_rows(d, d2, drop_column='a') # make sure that the repeated data was dropped assert 'nine' not in d['b'] print(_tsv_to_str(d)) d_path = tmp_path / 'output.tsv' # write the data to an output tsv file _to_tsv(d, d_path) # now read it back d = _from_tsv(d_path) # test reading the file in with the incorrect number of datatypes raises # an Error with pytest.raises(ValueError): d = _from_tsv(d_path, dtypes=[str]) # we can also pass just a single data type and it will be applied to all # columns d = _from_tsv(d_path, str) # remove any rows with 2 or 5 in them d = _drop(d, [2, 5], 'a') assert 2 not in d['a'] # test combining data with differing numbers of columns d = odict(a=[1, 2], b=['three', 'four']) d2 = odict(a=[4], b=['five'], c=[3.1415]) # raise error if a new column is tried to be added with pytest.raises(KeyError): d = _combine_rows(d, d2) d2 = odict(a=[5]) d = _combine_rows(d, d2) assert d['b'] == ['three', 'four', 'n/a'] assert _contains_row(d, {'a': 5}) # test reading a single column _to_tsv(odict(a=[1, 2, 3, 4]), d_path) d = _from_tsv(d_path) assert d['a'] == ['1', '2', '3', '4']
def _participants_tsv(raw, subject_id, fname, overwrite=False, verbose=True): """Create a participants.tsv file and save it. This will append any new participant data to the current list if it exists. Otherwise a new file will be created with the provided information. Parameters ---------- raw : instance of Raw The data as MNE-Python Raw object. subject_id : str The subject name in BIDS compatible format ('01', '02', etc.) fname : str Filename to save the participants.tsv to. overwrite : bool Whether to overwrite the existing file. Defaults to False. If there is already data for the given `subject_id` and overwrite is False, an error will be raised. verbose : bool Set verbose output to true or false. """ subject_id = 'sub-' + subject_id data = OrderedDict(participant_id=[subject_id]) subject_age = "n/a" sex = "n/a" subject_info = raw.info['subject_info'] if subject_info is not None: sexes = {0: 'n/a', 1: 'M', 2: 'F'} sex = sexes[subject_info.get('sex', 0)] # determine the age of the participant age = subject_info.get('birthday', None) meas_date = raw.info.get('meas_date', None) if isinstance(meas_date, (tuple, list, np.ndarray)): meas_date = meas_date[0] if meas_date is not None and age is not None: bday = datetime(age[0], age[1], age[2]) meas_datetime = datetime.fromtimestamp(meas_date) subject_age = _age_on_date(bday, meas_datetime) else: subject_age = "n/a" data.update({'age': [subject_age], 'sex': [sex]}) if os.path.exists(fname): orig_data = _from_tsv(fname) # whether the new data exists identically in the previous data exact_included = _contains_row(orig_data, {'participant_id': subject_id, 'age': subject_age, 'sex': sex}) # whether the subject id is in the previous data sid_included = subject_id in orig_data['participant_id'] # if the subject data provided is different to the currently existing # data and overwrite is not True raise an error if (sid_included and not exact_included) and not overwrite: raise FileExistsError('"%s" already exists in the participant ' # noqa: E501 F821 'list. Please set overwrite to ' 'True.' % subject_id) # otherwise add the new data data = _combine(orig_data, data, 'participant_id') # overwrite is forced to True as all issues with overwrite == False have # been handled by this point _write_tsv(fname, data, True, verbose) return fname