diff --git a/.github/workflows/io-test.yml b/.github/workflows/io-test.yml index a580b83d3..66690722c 100644 --- a/.github/workflows/io-test.yml +++ b/.github/workflows/io-test.yml @@ -103,6 +103,8 @@ jobs: sudo apt-get install -yqq --allow-downgrades libc6:i386 libgcc-s1:i386 libstdc++6:i386 wine - name: Test with pytest + env: + HDF5_PLUGIN_PATH: ${{ github.workspace }}/hdf5_local_plugin_path run: | # only neo.rawio and neo.io pytest --cov=neo neo/test/rawiotest diff --git a/doc/source/governance.rst b/doc/source/governance.rst index 767fbc72b..75158fa46 100644 --- a/doc/source/governance.rst +++ b/doc/source/governance.rst @@ -37,6 +37,7 @@ The current maintainers are: - Samuel Garcia (`@samuelgarcia`_) - Julia Sprenger (`@JuliaSprenger`_) - Michael Denker (`@mdenker`_) +- Alessio Buccino (`@alejoe91`_) .. _`Neo maintainers team`: https://github.com/orgs/NeuralEnsemble/teams/neo-maintainers @@ -45,3 +46,4 @@ The current maintainers are: .. _`@samuelgarcia`: https://github.com/samuelgarcia .. _`@JuliaSprenger`: https://github.com/JuliaSprenger .. _`@mdenker`: https://github.com/mdenker +.. _`@alejoe91`: https://github.com/alejoe91 diff --git a/neo/core/analogsignal.py b/neo/core/analogsignal.py index d4b45bcb3..f8fc98bb8 100644 --- a/neo/core/analogsignal.py +++ b/neo/core/analogsignal.py @@ -718,7 +718,7 @@ def concatenate(self, *signals, overwrite=False, padding=False): if padding is not False: logger.warning('Signals will be padded using {}.'.format(padding)) if padding is True: - padding = np.NaN * units + padding = np.nan * units if isinstance(padding, pq.Quantity): padding = padding.rescale(units).magnitude else: diff --git a/neo/io/klustakwikio.py b/neo/io/klustakwikio.py index ab8dd69ae..a580c4736 100644 --- a/neo/io/klustakwikio.py +++ b/neo/io/klustakwikio.py @@ -13,6 +13,7 @@ * Load features in addition to spiketimes. """ +import re import glob import logging from pathlib import Path @@ -439,7 +440,7 @@ def read_filenames(self, typestring='fet'): for v in all_filenames: # Test whether matches format, ie ends with digits split_fn = v.name - m = glob.re.search((r'^(\w+)\.%s\.(\d+)$' % typestring), split_fn) + m = re.search(rf'^(.*)\.{typestring}\.(\d+)$', split_fn) if m is not None: # get basename from first hit if not specified if self.basename is None: diff --git a/neo/rawio/__init__.py b/neo/rawio/__init__.py index 896a491fd..58173ed96 100644 --- a/neo/rawio/__init__.py +++ b/neo/rawio/__init__.py @@ -246,8 +246,18 @@ WinWcpRawIO, ] - def get_rawio_class(filename_or_dirname): + """Legacy function for returning class guess from file extension + DEPRECATED + """ + + import warnings + warnings.warn('get_rawio_class is deprecated. In the future please use get_rawio') + + return get_rawio(filename_or_dirname) + + +def get_rawio(filename_or_dirname): """ Return a neo.rawio class guess from file extension. """ diff --git a/neo/rawio/blackrockrawio.py b/neo/rawio/blackrockrawio.py index 6fea2064c..d0b6b2d77 100644 --- a/neo/rawio/blackrockrawio.py +++ b/neo/rawio/blackrockrawio.py @@ -1163,7 +1163,7 @@ def __get_event_segment_ids(self, raw_event_data, masks, nev_data_masks): raw_event_data['timestamp'][mask_handled][1:] < raw_event_data['timestamp'][mask_handled][:-1] )[0] + 1 jump_ids = np.where(mask_handled)[0][jump_ids_handled] # jump ids in full set of events (incl. unhandled) - overlap = np.in1d(jump_ids, reset_ev_ids) + overlap = np.isin(jump_ids, reset_ev_ids) if not all(overlap): # additional resets occurred without a reset event being stored additional_ids = jump_ids[np.invert(overlap)] @@ -2002,7 +2002,7 @@ def __get_nonneural_evdicts_variant_b(self, data): a 2.3 nev file. """ # digital events - if not np.all(np.in1d(data['packet_insertion_reason'], [1, 129])): + if not np.all(np.isin(data['packet_insertion_reason'], [1, 129])): # Blackrock spec gives reason==64 means PERIODIC, but never seen this live warnings.warn("Unknown event codes found", RuntimeWarning) event_types = { diff --git a/neo/rawio/intanrawio.py b/neo/rawio/intanrawio.py index b8c2ca097..68b94f7c0 100644 --- a/neo/rawio/intanrawio.py +++ b/neo/rawio/intanrawio.py @@ -27,7 +27,24 @@ class IntanRawIO(BaseRawIO): """ - + Intan reader can handle two file formats 'rhd' and 'rhs'. It will automatically + check for the file extension and will gather the header information based on the + extension. Additionally it functions with RHS v 1.0 and RHD 1.0, 1.1, 1.2, 1.3, 2.0, + 3.0, and 3.1 files. + Intan files contain amplifier channels labeled 'A', 'B' 'C' or 'D' + depending on the port in which they were recorded along with the following + additional channels. + 1: 'RHD2000 auxiliary input channel', + 2: 'RHD2000 supply voltage channel', + 3: 'USB board ADC input channel', + 4: 'USB board digital input channel', + 5: 'USB board digital output channel' + Due to the structure of the digital input and output channels these can be accessed + as one long vector, which must be post-processed. + Parameters + ---------- + filename: str + name of the 'rhd' or 'rhs' data file """ extensions = ['rhd', 'rhs'] rawmode = 'one-file' @@ -543,10 +560,17 @@ def read_rhd(filename): # 4: USB board digital input channel # 5: USB board digital output channel for sig_type in [4, 5]: - # at the moment theses channel are not in sig channel list - # but they are in the raw memamp + # Now these are included so that user can obtain the + # dig signals and process them at the same time if len(channels_by_type[sig_type]) > 0: name = {4: 'DIGITAL-IN', 5: 'DIGITAL-OUT'}[sig_type] + chan_info = channels_by_type[sig_type][0] + chan_info['native_channel_name'] = name # overwite to allow memmap to work + chan_info['sampling_rate'] = sr + chan_info['units'] = 'TTL' # arbitrary units so I did TTL for the logic + chan_info['gain'] = 1.0 + chan_info['offset'] = 0.0 + ordered_channels.append(chan_info) data_dtype += [(name, 'uint16', BLOCK_SIZE)] if bool(global_info['notch_filter_mode']) and version >= V('3.0'): diff --git a/neo/rawio/spikegadgetsrawio.py b/neo/rawio/spikegadgetsrawio.py index 26c54fa8a..0c6ac0071 100644 --- a/neo/rawio/spikegadgetsrawio.py +++ b/neo/rawio/spikegadgetsrawio.py @@ -183,10 +183,10 @@ def _parse_header(self): self.selected_streams = [self.selected_streams] assert isinstance(self.selected_streams, list) - keep = np.in1d(signal_streams['id'], self.selected_streams) + keep = np.isin(signal_streams['id'], self.selected_streams) signal_streams = signal_streams[keep] - keep = np.in1d(signal_channels['stream_id'], self.selected_streams) + keep = np.isin(signal_channels['stream_id'], self.selected_streams) signal_channels = signal_channels[keep] # No events channels diff --git a/neo/test/coretest/test_analogsignal.py b/neo/test/coretest/test_analogsignal.py index 521e4bdba..44c93b49a 100644 --- a/neo/test/coretest/test_analogsignal.py +++ b/neo/test/coretest/test_analogsignal.py @@ -1537,7 +1537,7 @@ def test_concatenate_padding_True(self): result = signal1.concatenate(signal2, overwrite=False, padding=True) assert_array_equal( - np.array([0, 1, 2, 3, np.NaN, np.NaN, np.NaN, 4, 5, 6]).reshape((-1, 1)), + np.array([0, 1, 2, 3, np.nan, np.nan, np.nan, 4, 5, 6]).reshape((-1, 1)), result.magnitude) def test_concatenate_padding_quantity(self): diff --git a/neo/test/coretest/test_base.py b/neo/test/coretest/test_base.py index 76e0051ca..0a51a95dc 100644 --- a/neo/test/coretest/test_base.py +++ b/neo/test/coretest/test_base.py @@ -853,7 +853,7 @@ def test_numpy_array_uint64(self): def test_numpy_array_float(self): '''test to make sure float type numpy arrays are accepted''' - value = np.array([1, 2, 3, 4, 5], dtype=np.float_) + value = np.array([1, 2, 3, 4, 5], dtype=np.float64) self.base.annotate(data=value) result = {'data': value} self.assertDictEqual(result, self.base.annotations) @@ -1041,7 +1041,7 @@ def test_numpy_scalar_uint64(self): def test_numpy_scalar_float(self): '''test to make sure float type numpy scalars are accepted''' - value = np.array(99, dtype=np.float_) + value = np.array(99, dtype=np.float64) self.base.annotate(data=value) result = {'data': value} self.assertDictEqual(result, self.base.annotations) diff --git a/neo/test/coretest/test_spiketrain.py b/neo/test/coretest/test_spiketrain.py index 8990b69f9..be038b327 100644 --- a/neo/test/coretest/test_spiketrain.py +++ b/neo/test/coretest/test_spiketrain.py @@ -580,8 +580,8 @@ def test_defaults(self): train2 = _new_spiketrain(SpikeTrain, [3, 4, 5], units='sec', t_stop=10.0) assert_neo_object_is_compliant(train1) assert_neo_object_is_compliant(train2) - self.assertEqual(train1.dtype, np.float_) - self.assertEqual(train2.dtype, np.float_) + self.assertEqual(train1.dtype, np.float64) + self.assertEqual(train2.dtype, np.float64) self.assertEqual(train1.sampling_rate, 1.0 * pq.Hz) self.assertEqual(train2.sampling_rate, 1.0 * pq.Hz) self.assertEqual(train1.waveforms, None) diff --git a/neo/test/iotest/test_asciisignalio.py b/neo/test/iotest/test_asciisignalio.py index 4e6a03754..20e587112 100644 --- a/neo/test/iotest/test_asciisignalio.py +++ b/neo/test/iotest/test_asciisignalio.py @@ -55,7 +55,7 @@ def test_csv_expect_success(self): (-64.6, -64.2, -77.0, 0.7), (-64.3, -64.0, -99.9, 0.8) ] - with open(filename, 'w') as csvfile: + with open(filename, 'w', newline='') as csvfile: writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) for row in sample_data: diff --git a/neo/test/iotest/test_nestio.py b/neo/test/iotest/test_nestio.py index 6d0fe6012..448a0a520 100644 --- a/neo/test/iotest/test_nestio.py +++ b/neo/test/iotest/test_nestio.py @@ -356,7 +356,7 @@ def test_read_float(self): t_stop=500. * pq.ms, lazy=False, id_column_gdf=0, time_column_gdf=1) sts = seg.spiketrains - self.assertTrue(all([s.magnitude.dtype == np.float_ for s in sts])) + self.assertTrue(all([s.magnitude.dtype == np.float64 for s in sts])) def test_values(self): """ diff --git a/neo/test/rawiotest/test_get_rawio.py b/neo/test/rawiotest/test_get_rawio.py index 3f3e7f6a5..2567077ee 100644 --- a/neo/test/rawiotest/test_get_rawio.py +++ b/neo/test/rawiotest/test_get_rawio.py @@ -1,4 +1,4 @@ -from neo.rawio import get_rawio_class +from neo.rawio import get_rawio from pathlib import Path from tempfile import TemporaryDirectory @@ -7,7 +7,7 @@ def test_get_rawio_class(): # use plexon io suffix for testing here non_existant_file = Path('non_existant_folder/non_existant_file.plx') non_existant_file.unlink(missing_ok=True) - ios = get_rawio_class(non_existant_file) + ios = get_rawio(non_existant_file) assert ios @@ -19,7 +19,7 @@ def test_get_rawio_class_nonsupported_rawio(): non_existant_file = Path('non_existant_folder/non_existant_file.fake') non_existant_file.unlink(missing_ok=True) - ios = get_rawio_class(non_existant_file) + ios = get_rawio(non_existant_file) assert ios is None diff --git a/neo/utils/misc.py b/neo/utils/misc.py index eb2937823..780acb4ee 100644 --- a/neo/utils/misc.py +++ b/neo/utils/misc.py @@ -247,13 +247,13 @@ def _get_valid_ids(obj, annotation_key, annotation_value): # wrap annotation value to be list if not type(annotation_value) in [list, np.ndarray]: annotation_value = [annotation_value] - valid_mask = np.in1d(obj.labels, annotation_value) + valid_mask = np.isin(obj.labels, annotation_value) elif annotation_key in obj.array_annotations: # wrap annotation value to be list if not type(annotation_value) in [list, np.ndarray]: annotation_value = [annotation_value] - valid_mask = np.in1d(obj.array_annotations[annotation_key], annotation_value) + valid_mask = np.isin(obj.array_annotations[annotation_key], annotation_value) elif hasattr(obj, annotation_key) and getattr(obj, annotation_key) == annotation_value: valid_mask = np.ones(obj.shape)