eegdash 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of eegdash might be problematic. Click here for more details.

Files changed (72) hide show
  1. eegdash/SignalStore/__init__.py +0 -0
  2. eegdash/SignalStore/signalstore/__init__.py +3 -0
  3. eegdash/SignalStore/signalstore/adapters/read_adapters/abstract_read_adapter.py +13 -0
  4. eegdash/SignalStore/signalstore/adapters/read_adapters/domain_modeling/schema_read_adapter.py +16 -0
  5. eegdash/SignalStore/signalstore/adapters/read_adapters/domain_modeling/vocabulary_read_adapter.py +19 -0
  6. eegdash/SignalStore/signalstore/adapters/read_adapters/handmade_records/excel_study_organizer_read_adapter.py +114 -0
  7. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/axona/axona_read_adapter.py +912 -0
  8. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/ReadIntanSpikeFile.py +140 -0
  9. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/intan_read_adapter.py +29 -0
  10. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/__init__.py +0 -0
  11. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/data_to_result.py +62 -0
  12. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/get_bytes_per_data_block.py +36 -0
  13. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/notch_filter.py +50 -0
  14. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/qstring.py +41 -0
  15. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/read_header.py +135 -0
  16. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/intanutil/read_one_data_block.py +45 -0
  17. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhd_format/load_intan_rhd_format.py +204 -0
  18. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/__init__.py +0 -0
  19. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/data_to_result.py +60 -0
  20. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/get_bytes_per_data_block.py +37 -0
  21. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/notch_filter.py +50 -0
  22. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/qstring.py +41 -0
  23. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/read_header.py +153 -0
  24. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/intanutil/read_one_data_block.py +47 -0
  25. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/intan/load_intan_rhs_format/load_intan_rhs_format.py +213 -0
  26. eegdash/SignalStore/signalstore/adapters/read_adapters/recording_acquisitions/neurodata_without_borders/neurodata_without_borders_read_adapter.py +14 -0
  27. eegdash/SignalStore/signalstore/operations/__init__.py +4 -0
  28. eegdash/SignalStore/signalstore/operations/handler_executor.py +22 -0
  29. eegdash/SignalStore/signalstore/operations/handler_factory.py +41 -0
  30. eegdash/SignalStore/signalstore/operations/handlers/base_handler.py +44 -0
  31. eegdash/SignalStore/signalstore/operations/handlers/domain/property_model_handlers.py +79 -0
  32. eegdash/SignalStore/signalstore/operations/handlers/domain/schema_handlers.py +3 -0
  33. eegdash/SignalStore/signalstore/operations/helpers/abstract_helper.py +17 -0
  34. eegdash/SignalStore/signalstore/operations/helpers/neuroscikit_extractor.py +33 -0
  35. eegdash/SignalStore/signalstore/operations/helpers/neuroscikit_rawio.py +165 -0
  36. eegdash/SignalStore/signalstore/operations/helpers/spikeinterface_helper.py +100 -0
  37. eegdash/SignalStore/signalstore/operations/helpers/wrappers/neo_wrappers.py +21 -0
  38. eegdash/SignalStore/signalstore/operations/helpers/wrappers/nwb_wrappers.py +27 -0
  39. eegdash/SignalStore/signalstore/store/__init__.py +8 -0
  40. eegdash/SignalStore/signalstore/store/data_access_objects.py +1181 -0
  41. eegdash/SignalStore/signalstore/store/datafile_adapters.py +131 -0
  42. eegdash/SignalStore/signalstore/store/repositories.py +928 -0
  43. eegdash/SignalStore/signalstore/store/store_errors.py +68 -0
  44. eegdash/SignalStore/signalstore/store/unit_of_work.py +97 -0
  45. eegdash/SignalStore/signalstore/store/unit_of_work_provider.py +67 -0
  46. eegdash/SignalStore/signalstore/utilities/data_adapters/spike_interface_adapters/si_recording.py +1 -0
  47. eegdash/SignalStore/signalstore/utilities/data_adapters/spike_interface_adapters/si_sorter.py +1 -0
  48. eegdash/SignalStore/signalstore/utilities/testing/data_mocks.py +513 -0
  49. eegdash/SignalStore/signalstore/utilities/tools/dataarrays.py +49 -0
  50. eegdash/SignalStore/signalstore/utilities/tools/mongo_records.py +25 -0
  51. eegdash/SignalStore/signalstore/utilities/tools/operation_response.py +78 -0
  52. eegdash/SignalStore/signalstore/utilities/tools/purge_orchestration_response.py +21 -0
  53. eegdash/SignalStore/signalstore/utilities/tools/quantities.py +15 -0
  54. eegdash/SignalStore/signalstore/utilities/tools/strings.py +38 -0
  55. eegdash/SignalStore/signalstore/utilities/tools/time.py +17 -0
  56. eegdash/SignalStore/tests/conftest.py +799 -0
  57. eegdash/SignalStore/tests/data/valid_data/data_arrays/make_fake_data.py +59 -0
  58. eegdash/SignalStore/tests/unit/store/conftest.py +0 -0
  59. eegdash/SignalStore/tests/unit/store/test_data_access_objects.py +1235 -0
  60. eegdash/SignalStore/tests/unit/store/test_repositories.py +1309 -0
  61. eegdash/SignalStore/tests/unit/store/test_unit_of_work.py +7 -0
  62. eegdash/SignalStore/tests/unit/test_ci_cd.py +8 -0
  63. eegdash/__init__.py +1 -0
  64. eegdash/aws_ingest.py +29 -0
  65. eegdash/data_utils.py +213 -0
  66. eegdash/main.py +17 -0
  67. eegdash/signalstore_data_utils.py +280 -0
  68. eegdash-0.0.1.dist-info/LICENSE +20 -0
  69. eegdash-0.0.1.dist-info/METADATA +72 -0
  70. eegdash-0.0.1.dist-info/RECORD +72 -0
  71. eegdash-0.0.1.dist-info/WHEEL +5 -0
  72. eegdash-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,204 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 17 July 2015
4
+ # Modified Adrian Foy January 2023
5
+
6
+ import sys, struct, math, os, time
7
+ import numpy as np
8
+
9
+ from intanutil.read_header import read_header
10
+ from intanutil.get_bytes_per_data_block import get_bytes_per_data_block
11
+ from intanutil.read_one_data_block import read_one_data_block
12
+ from intanutil.notch_filter import notch_filter
13
+ from intanutil.data_to_result import data_to_result
14
+
15
+
16
+ def read_data(filename):
17
+ """Reads Intan Technologies RHD2000 data file generated by evaluation board GUI.
18
+
19
+ Data are returned in a dictionary, for future extensibility.
20
+ """
21
+
22
+ tic = time.time()
23
+ fid = open(filename, 'rb')
24
+ filesize = os.path.getsize(filename)
25
+
26
+ header = read_header(fid)
27
+
28
+ print('Found {} amplifier channel{}.'.format(header['num_amplifier_channels'], plural(header['num_amplifier_channels'])))
29
+ print('Found {} auxiliary input channel{}.'.format(header['num_aux_input_channels'], plural(header['num_aux_input_channels'])))
30
+ print('Found {} supply voltage channel{}.'.format(header['num_supply_voltage_channels'], plural(header['num_supply_voltage_channels'])))
31
+ print('Found {} board ADC channel{}.'.format(header['num_board_adc_channels'], plural(header['num_board_adc_channels'])))
32
+ print('Found {} board digital input channel{}.'.format(header['num_board_dig_in_channels'], plural(header['num_board_dig_in_channels'])))
33
+ print('Found {} board digital output channel{}.'.format(header['num_board_dig_out_channels'], plural(header['num_board_dig_out_channels'])))
34
+ print('Found {} temperature sensors channel{}.'.format(header['num_temp_sensor_channels'], plural(header['num_temp_sensor_channels'])))
35
+ print('')
36
+
37
+ # Determine how many samples the data file contains.
38
+ bytes_per_block = get_bytes_per_data_block(header)
39
+
40
+ # How many data blocks remain in this file?
41
+ data_present = False
42
+ bytes_remaining = filesize - fid.tell()
43
+ if bytes_remaining > 0:
44
+ data_present = True
45
+
46
+ if bytes_remaining % bytes_per_block != 0:
47
+ raise Exception('Something is wrong with file size : should have a whole number of data blocks')
48
+
49
+ num_data_blocks = int(bytes_remaining / bytes_per_block)
50
+
51
+ num_amplifier_samples = header['num_samples_per_data_block'] * num_data_blocks
52
+ num_aux_input_samples = int((header['num_samples_per_data_block'] / 4) * num_data_blocks)
53
+ num_supply_voltage_samples = 1 * num_data_blocks
54
+ num_board_adc_samples = header['num_samples_per_data_block'] * num_data_blocks
55
+ num_board_dig_in_samples = header['num_samples_per_data_block'] * num_data_blocks
56
+ num_board_dig_out_samples = header['num_samples_per_data_block'] * num_data_blocks
57
+
58
+ record_time = num_amplifier_samples / header['sample_rate']
59
+
60
+ if data_present:
61
+ print('File contains {:0.3f} seconds of data. Amplifiers were sampled at {:0.2f} kS/s.'.format(record_time, header['sample_rate'] / 1000))
62
+ else:
63
+ print('Header file contains no data. Amplifiers were sampled at {:0.2f} kS/s.'.format(header['sample_rate'] / 1000))
64
+
65
+ if data_present:
66
+ # Pre-allocate memory for data.
67
+ print('')
68
+ print('Allocating memory for data...')
69
+
70
+ data = {}
71
+ if (header['version']['major'] == 1 and header['version']['minor'] >= 2) or (header['version']['major'] > 1):
72
+ data['t_amplifier'] = np.zeros(num_amplifier_samples, dtype=np.int_)
73
+ else:
74
+ data['t_amplifier'] = np.zeros(num_amplifier_samples, dtype=np.uint)
75
+
76
+ data['amplifier_data'] = np.zeros([header['num_amplifier_channels'], num_amplifier_samples], dtype=np.uint)
77
+ data['aux_input_data'] = np.zeros([header['num_aux_input_channels'], num_aux_input_samples], dtype=np.uint)
78
+ data['supply_voltage_data'] = np.zeros([header['num_supply_voltage_channels'], num_supply_voltage_samples], dtype=np.uint)
79
+ data['temp_sensor_data'] = np.zeros([header['num_temp_sensor_channels'], num_supply_voltage_samples], dtype=np.uint)
80
+ data['board_adc_data'] = np.zeros([header['num_board_adc_channels'], num_board_adc_samples], dtype=np.uint)
81
+
82
+ # by default, this script interprets digital events (digital inputs and outputs) as booleans
83
+ # if unsigned int values are preferred(0 for False, 1 for True), replace the 'dtype=np.bool_' argument with 'dtype=np.uint' as shown
84
+ # the commented line below illustrates this for digital input data; the same can be done for digital out
85
+
86
+ #data['board_dig_in_data'] = np.zeros([header['num_board_dig_in_channels'], num_board_dig_in_samples], dtype=np.uint)
87
+ data['board_dig_in_data'] = np.zeros([header['num_board_dig_in_channels'], num_board_dig_in_samples], dtype=np.bool_)
88
+ data['board_dig_in_raw'] = np.zeros(num_board_dig_in_samples, dtype=np.uint)
89
+
90
+ data['board_dig_out_data'] = np.zeros([header['num_board_dig_out_channels'], num_board_dig_out_samples], dtype=np.bool_)
91
+ data['board_dig_out_raw'] = np.zeros(num_board_dig_out_samples, dtype=np.uint)
92
+
93
+ # Read sampled data from file.
94
+ print('Reading data from file...')
95
+
96
+ # Initialize indices used in looping
97
+ indices = {}
98
+ indices['amplifier'] = 0
99
+ indices['aux_input'] = 0
100
+ indices['supply_voltage'] = 0
101
+ indices['board_adc'] = 0
102
+ indices['board_dig_in'] = 0
103
+ indices['board_dig_out'] = 0
104
+
105
+ print_increment = 10
106
+ percent_done = print_increment
107
+ for i in range(num_data_blocks):
108
+ read_one_data_block(data, header, indices, fid)
109
+
110
+ # Increment indices
111
+ indices['amplifier'] += header['num_samples_per_data_block']
112
+ indices['aux_input'] += int(header['num_samples_per_data_block'] / 4)
113
+ indices['supply_voltage'] += 1
114
+ indices['board_adc'] += header['num_samples_per_data_block']
115
+ indices['board_dig_in'] += header['num_samples_per_data_block']
116
+ indices['board_dig_out'] += header['num_samples_per_data_block']
117
+
118
+ fraction_done = 100 * (1.0 * i / num_data_blocks)
119
+ if fraction_done >= percent_done:
120
+ print('{}% done...'.format(percent_done))
121
+ percent_done = percent_done + print_increment
122
+
123
+ # Make sure we have read exactly the right amount of data.
124
+ bytes_remaining = filesize - fid.tell()
125
+ if bytes_remaining != 0: raise Exception('Error: End of file not reached.')
126
+
127
+
128
+
129
+ # Close data file.
130
+ fid.close()
131
+
132
+ if (data_present):
133
+ print('Parsing data...')
134
+
135
+ # Extract digital input channels to separate variables.
136
+ for i in range(header['num_board_dig_in_channels']):
137
+ data['board_dig_in_data'][i, :] = np.not_equal(np.bitwise_and(data['board_dig_in_raw'], (1 << header['board_dig_in_channels'][i]['native_order'])), 0)
138
+
139
+ # Extract digital output channels to separate variables.
140
+ for i in range(header['num_board_dig_out_channels']):
141
+ data['board_dig_out_data'][i, :] = np.not_equal(np.bitwise_and(data['board_dig_out_raw'], (1 << header['board_dig_out_channels'][i]['native_order'])), 0)
142
+
143
+ # Scale voltage levels appropriately.
144
+ data['amplifier_data'] = np.multiply(0.195, (data['amplifier_data'].astype(np.int32) - 32768)) # units = microvolts
145
+ data['aux_input_data'] = np.multiply(37.4e-6, data['aux_input_data']) # units = volts
146
+ data['supply_voltage_data'] = np.multiply(74.8e-6, data['supply_voltage_data']) # units = volts
147
+ if header['eval_board_mode'] == 1:
148
+ data['board_adc_data'] = np.multiply(152.59e-6, (data['board_adc_data'].astype(np.int32) - 32768)) # units = volts
149
+ elif header['eval_board_mode'] == 13:
150
+ data['board_adc_data'] = np.multiply(312.5e-6, (data['board_adc_data'].astype(np.int32) - 32768)) # units = volts
151
+ else:
152
+ data['board_adc_data'] = np.multiply(50.354e-6, data['board_adc_data']) # units = volts
153
+ data['temp_sensor_data'] = np.multiply(0.01, data['temp_sensor_data']) # units = deg C
154
+
155
+ # Check for gaps in timestamps.
156
+ num_gaps = np.sum(np.not_equal(data['t_amplifier'][1:]-data['t_amplifier'][:-1], 1))
157
+ if num_gaps == 0:
158
+ print('No missing timestamps in data.')
159
+ else:
160
+ print('Warning: {0} gaps in timestamp data found. Time scale will not be uniform!'.format(num_gaps))
161
+
162
+ # Scale time steps (units = seconds).
163
+ data['t_amplifier'] = data['t_amplifier'] / header['sample_rate']
164
+ data['t_aux_input'] = data['t_amplifier'][range(0, len(data['t_amplifier']), 4)]
165
+ data['t_supply_voltage'] = data['t_amplifier'][range(0, len(data['t_amplifier']), header['num_samples_per_data_block'])]
166
+ data['t_board_adc'] = data['t_amplifier']
167
+ data['t_dig'] = data['t_amplifier']
168
+ data['t_temp_sensor'] = data['t_supply_voltage']
169
+
170
+ # If the software notch filter was selected during the recording, apply the
171
+ # same notch filter to amplifier data here.
172
+ if header['notch_filter_frequency'] > 0 and header['version']['major'] < 3:
173
+ print('Applying notch filter...')
174
+
175
+ print_increment = 10
176
+ percent_done = print_increment
177
+ for i in range(header['num_amplifier_channels']):
178
+ data['amplifier_data'][i,:] = notch_filter(data['amplifier_data'][i,:], header['sample_rate'], header['notch_filter_frequency'], 10)
179
+
180
+ fraction_done = 100 * (i / header['num_amplifier_channels'])
181
+ if fraction_done >= percent_done:
182
+ print('{}% done...'.format(percent_done))
183
+ percent_done += print_increment
184
+ else:
185
+ data = [];
186
+
187
+ # Move variables to result struct.
188
+ result = data_to_result(header, data, data_present)
189
+
190
+ print('Done! Elapsed time: {0:0.1f} seconds'.format(time.time() - tic))
191
+ return result
192
+
193
+ def plural(n):
194
+ """Utility function to optionally pluralize words based on the value of n.
195
+ """
196
+
197
+ if n == 1:
198
+ return ''
199
+ else:
200
+ return 's'
201
+
202
+ if __name__ == '__main__':
203
+ a=read_data(sys.argv[1])
204
+ #print(a)
@@ -0,0 +1,60 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 27 April 2015
4
+ # Modified Zeke Arneodo Dec 2017
5
+ # Modified Adrian Foy Sep 2018
6
+
7
+ def data_to_result(header, data, data_present):
8
+ """Moves the header and data (if present) into a common object."""
9
+
10
+ result = {}
11
+ result['t'] = data['t']
12
+
13
+ stim_parameters = {}
14
+ stim_parameters['stim_step_size'] = header['stim_step_size']
15
+ stim_parameters['charge_recovery_current_limit'] = header['recovery_current_limit']
16
+ stim_parameters['charge_recovery_target_voltage'] = header['recovery_target_voltage']
17
+ stim_parameters['amp_settle_mode'] = header['amp_settle_mode']
18
+ stim_parameters['charge_recovery_mode'] = header['charge_recovery_mode']
19
+ result['stim_parameters'] = stim_parameters
20
+
21
+ result['stim_data'] = data['stim_data']
22
+ result['spike_triggers'] = header['spike_triggers']
23
+ result['notes'] = header['notes']
24
+ result['frequency_parameters'] = header['frequency_parameters']
25
+
26
+ if header['dc_amplifier_data_saved']:
27
+ result['dc_amplifier_data'] = data['dc_amplifier_data']
28
+
29
+ if header['num_amplifier_channels'] > 0:
30
+ if data_present:
31
+ result['compliance_limit_data'] = data['compliance_limit_data']
32
+ result['charge_recovery_data'] = data['charge_recovery_data']
33
+ result['amp_settle_data'] = data['amp_settle_data']
34
+
35
+ if header['num_board_dig_out_channels'] > 0:
36
+ result['board_dig_out_channels'] = header['board_dig_out_channels']
37
+ if data_present:
38
+ result['board_dig_out_data'] = data['board_dig_out_data']
39
+
40
+ if header['num_board_dig_in_channels'] > 0:
41
+ result['board_dig_in_channels'] = header['board_dig_in_channels']
42
+ if data_present:
43
+ result['board_dig_in_data'] = data['board_dig_in_data']
44
+
45
+ if header['num_board_dac_channels'] > 0:
46
+ result['board_dac_channels'] = header['board_dac_channels']
47
+ if data_present:
48
+ result['board_dac_data'] = data['board_dac_data']
49
+
50
+ if header['num_board_adc_channels'] > 0:
51
+ result['board_adc_channels'] = header['board_adc_channels']
52
+ if data_present:
53
+ result['board_adc_data'] = data['board_adc_data']
54
+
55
+ if header['num_amplifier_channels'] > 0:
56
+ result['amplifier_channels'] = header['amplifier_channels']
57
+ if data_present:
58
+ result['amplifier_data'] = data['amplifier_data']
59
+
60
+ return result
@@ -0,0 +1,37 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 23 April 2015
4
+ # Modified Zeke Arneodo Dec 2017
5
+ # Modified Adrian Foy Sep 2018
6
+
7
+ def get_bytes_per_data_block(header):
8
+ """Calculates the number of bytes in each 128-sample datablock."""
9
+ N = 128 # n of amplifier samples
10
+ # Each data block contains N amplifier samples.
11
+ bytes_per_block = N * 4 # timestamp data
12
+
13
+ bytes_per_block += N * 2 * header['num_amplifier_channels']
14
+
15
+ # DC amplifier voltage (absent if flag was off)
16
+ # bytes_per_block += N * 2 * header['dc_amplifier_data_saved']
17
+ if header['dc_amplifier_data_saved'] > 0:
18
+ bytes_per_block += N * 2 * header['num_amplifier_channels']
19
+
20
+ # Stimulation data, one per enabled amplifier channels
21
+ bytes_per_block += N * 2 * header['num_amplifier_channels']
22
+
23
+ # Board analog inputs are sampled at same rate as amplifiers
24
+ bytes_per_block += N * 2 * header['num_board_adc_channels']
25
+
26
+ # Board analog outputs are sampled at same rate as amplifiers
27
+ bytes_per_block += N * 2 * header['num_board_dac_channels']
28
+
29
+ # Board digital inputs are sampled at same rate as amplifiers
30
+ if header['num_board_dig_in_channels'] > 0:
31
+ bytes_per_block += N * 2
32
+
33
+ # Board digital outputs are sampled at same rate as amplifiers
34
+ if header['num_board_dig_out_channels'] > 0:
35
+ bytes_per_block += N * 2
36
+
37
+ return bytes_per_block
@@ -0,0 +1,50 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 27 April 2015
4
+
5
+ import math
6
+ import numpy as np
7
+
8
+ def notch_filter(input, fSample, fNotch, Bandwidth):
9
+ """Implements a notch filter (e.g., for 50 or 60 Hz) on vector 'input'.
10
+
11
+ fSample = sample rate of data (input Hz or Samples/sec)
12
+ fNotch = filter notch frequency (input Hz)
13
+ Bandwidth = notch 3-dB bandwidth (input Hz). A bandwidth of 10 Hz is
14
+ recommended for 50 or 60 Hz notch filters; narrower bandwidths lead to
15
+ poor time-domain properties with an extended ringing response to
16
+ transient disturbances.
17
+
18
+ Example: If neural data was sampled at 30 kSamples/sec
19
+ and you wish to implement a 60 Hz notch filter:
20
+
21
+ out = notch_filter(input, 30000, 60, 10);
22
+ """
23
+
24
+ tstep = 1.0/fSample
25
+ Fc = fNotch*tstep
26
+
27
+ L = len(input)
28
+
29
+ # Calculate IIR filter parameters
30
+ d = math.exp(-2.0*math.pi*(Bandwidth/2.0)*tstep)
31
+ b = (1.0 + d*d) * math.cos(2.0*math.pi*Fc)
32
+ a0 = 1.0
33
+ a1 = -b
34
+ a2 = d*d
35
+ a = (1.0 + d*d)/2.0
36
+ b0 = 1.0
37
+ b1 = -2.0 * math.cos(2.0*math.pi*Fc)
38
+ b2 = 1.0
39
+
40
+ out = np.zeros(len(input))
41
+ out[0] = input[0]
42
+ out[1] = input[1]
43
+ # (If filtering a continuous data stream, change out[0:1] to the
44
+ # previous final two values of out.)
45
+
46
+ # Run filter
47
+ for i in range(2,L):
48
+ out[i] = (a*b2*input[i-2] + a*b1*input[i-1] + a*b0*input[i] - a2*out[i-2] - a1*out[i-1])/a0
49
+
50
+ return out
@@ -0,0 +1,41 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 23 April 2015
4
+
5
+
6
+ import sys, struct, os
7
+
8
+ def read_qstring(fid):
9
+ """Read Qt style QString.
10
+
11
+ The first 32-bit unsigned number indicates the length of the string (in bytes).
12
+ If this number equals 0xFFFFFFFF, the string is null.
13
+
14
+ Strings are stored as unicode.
15
+ """
16
+
17
+ length, = struct.unpack('<I', fid.read(4))
18
+ if length == int('ffffffff', 16): return ""
19
+
20
+ if length > (os.fstat(fid.fileno()).st_size - fid.tell() + 1) :
21
+ print(length)
22
+ raise Exception('Length too long.')
23
+
24
+ # convert length from bytes to 16-bit Unicode words
25
+ length = int(length / 2)
26
+
27
+ data = []
28
+ for i in range(0, length):
29
+ c, = struct.unpack('<H', fid.read(2))
30
+ data.append(c)
31
+
32
+ if sys.version_info >= (3,0):
33
+ a = ''.join([chr(c) for c in data])
34
+ else:
35
+ a = ''.join([unichr(c) for c in data])
36
+
37
+ return a
38
+
39
+ if __name__ == '__main__':
40
+ a=read_qstring(open(sys.argv[1], 'rb'))
41
+ print(a)
@@ -0,0 +1,153 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 23 April 2015
4
+ # Modified Zeke Arneodo Dec 2017
5
+ # Modified Adrian Foy Sep 2018
6
+
7
+ import sys, struct
8
+ from intanutil.qstring import read_qstring
9
+
10
+
11
+ def read_header(fid):
12
+ """Reads the Intan File Format header from the given file."""
13
+
14
+ # Check 'magic number' at beginning of file to make sure this is an Intan
15
+ # Technologies RHD2000 data file.
16
+ magic_number, = struct.unpack('<I', fid.read(4))
17
+
18
+ if magic_number != int('0xD69127AC', 16): raise Exception('Unrecognized file type.')
19
+
20
+ header = {}
21
+ # Read version number.
22
+ version = {}
23
+ (version['major'], version['minor']) = struct.unpack('<hh', fid.read(4))
24
+ header['version'] = version
25
+
26
+ print('')
27
+ print('Reading Intan Technologies RHS2000 Data File, Version {}.{}'.format(version['major'], version['minor']))
28
+ print('')
29
+
30
+ # Read information of sampling rate and amplifier frequency settings.
31
+ header['sample_rate'], = struct.unpack('<f', fid.read(4))
32
+ (header['dsp_enabled'],
33
+ header['actual_dsp_cutoff_frequency'],
34
+ header['actual_lower_bandwidth'],
35
+ header['actual_lower_settle_bandwidth'],
36
+ header['actual_upper_bandwidth'],
37
+ header['desired_dsp_cutoff_frequency'],
38
+ header['desired_lower_bandwidth'],
39
+ header['desired_lower_settle_bandwidth'],
40
+ header['desired_upper_bandwidth']) = struct.unpack('<hffffffff', fid.read(34))
41
+
42
+
43
+ # This tells us if a software 50/60 Hz notch filter was enabled during
44
+ # the data acquisition.
45
+ notch_filter_mode, = struct.unpack('<h', fid.read(2))
46
+ header['notch_filter_frequency'] = 0
47
+ if notch_filter_mode == 1:
48
+ header['notch_filter_frequency'] = 50
49
+ elif notch_filter_mode == 2:
50
+ header['notch_filter_frequency'] = 60
51
+
52
+ (header['desired_impedance_test_frequency'], header['actual_impedance_test_frequency']) = struct.unpack('<ff', fid.read(8))
53
+ (header['amp_settle_mode'], header['charge_recovery_mode']) = struct.unpack('<hh', fid.read(4))
54
+
55
+ frequency_parameters = {}
56
+ frequency_parameters['amplifier_sample_rate'] = header['sample_rate']
57
+ frequency_parameters['board_adc_sample_rate'] = header['sample_rate']
58
+ frequency_parameters['board_dig_in_sample_rate'] = header['sample_rate']
59
+ frequency_parameters['desired_dsp_cutoff_frequency'] = header['desired_dsp_cutoff_frequency']
60
+ frequency_parameters['actual_dsp_cutoff_frequency'] = header['actual_dsp_cutoff_frequency']
61
+ frequency_parameters['dsp_enabled'] = header['dsp_enabled']
62
+ frequency_parameters['desired_lower_bandwidth'] = header['desired_lower_bandwidth']
63
+ frequency_parameters['desired_lower_settle_bandwidth'] = header['desired_lower_settle_bandwidth']
64
+ frequency_parameters['actual_lower_bandwidth'] = header['actual_lower_bandwidth']
65
+ frequency_parameters['actual_lower_settle_bandwidth'] = header['actual_lower_settle_bandwidth']
66
+ frequency_parameters['desired_upper_bandwidth'] = header['desired_upper_bandwidth']
67
+ frequency_parameters['actual_upper_bandwidth'] = header['actual_upper_bandwidth']
68
+ frequency_parameters['notch_filter_frequency'] = header['notch_filter_frequency']
69
+ frequency_parameters['desired_impedance_test_frequency'] = header['desired_impedance_test_frequency']
70
+ frequency_parameters['actual_impedance_test_frequency'] = header['actual_impedance_test_frequency']
71
+
72
+ header['frequency_parameters'] = frequency_parameters
73
+
74
+ (header['stim_step_size'],
75
+ header['recovery_current_limit'],
76
+ header['recovery_target_voltage']) = struct.unpack('fff', fid.read(12))
77
+
78
+ note1 = read_qstring(fid)
79
+ note2 = read_qstring(fid)
80
+ note3 = read_qstring(fid)
81
+ header['notes'] = { 'note1' : note1, 'note2' : note2, 'note3' : note3}
82
+
83
+ (header['dc_amplifier_data_saved'],
84
+ header['eval_board_mode']) = struct.unpack('<hh', fid.read(4))
85
+
86
+ header['ref_channel_name'] = read_qstring(fid)
87
+
88
+ # Create structure arrays for each type of data channel.
89
+ header['spike_triggers'] = []
90
+ header['amplifier_channels'] = []
91
+ header['board_adc_channels'] = []
92
+ header['board_dac_channels'] = []
93
+ header['board_dig_in_channels'] = []
94
+ header['board_dig_out_channels'] = []
95
+
96
+ # Read signal summary from data file header.
97
+ number_of_signal_groups, = struct.unpack('<h', fid.read(2))
98
+ print('n signal groups {}'.format(number_of_signal_groups))
99
+
100
+ for signal_group in range(1, number_of_signal_groups + 1):
101
+ signal_group_name = read_qstring(fid)
102
+ signal_group_prefix = read_qstring(fid)
103
+ (signal_group_enabled, signal_group_num_channels, signal_group_num_amp_channels) = struct.unpack('<hhh', fid.read(6))
104
+
105
+ if (signal_group_num_channels > 0) and (signal_group_enabled > 0):
106
+ for signal_channel in range(0, signal_group_num_channels):
107
+ new_channel = {'port_name' : signal_group_name, 'port_prefix' : signal_group_prefix, 'port_number' : signal_group}
108
+ new_channel['native_channel_name'] = read_qstring(fid)
109
+ new_channel['custom_channel_name'] = read_qstring(fid)
110
+ (new_channel['native_order'], new_channel['custom_order'],
111
+ signal_type, channel_enabled, new_channel['chip_channel'],
112
+ command_stream, new_channel['board_stream']) = struct.unpack('<hhhhhhh', fid.read(14)) # ignore command_stream
113
+ new_trigger_channel = {}
114
+ (new_trigger_channel['voltage_trigger_mode'],
115
+ new_trigger_channel['voltage_threshold'],
116
+ new_trigger_channel['digital_trigger_channel'],
117
+ new_trigger_channel['digital_edge_polarity']) = struct.unpack('<hhhh', fid.read(8))
118
+ (new_channel['channel_impedance_magnitude'],
119
+ new_channel['channel_impedance_phase']) = struct.unpack('<ff', fid.read(8))
120
+
121
+ if channel_enabled:
122
+ if signal_type == 0:
123
+ header['amplifier_channels'].append(new_channel)
124
+ header['spike_triggers'].append(new_trigger_channel)
125
+ elif signal_type == 1:
126
+ raise Exception('Wrong signal type for the rhs format')
127
+ #header['aux_input_channels'].append(new_channel)
128
+ elif signal_type == 2:
129
+ raise Exception('Wrong signal type for the rhs format')
130
+ #header['supply_voltage_channels'].append(new_channel)
131
+ elif signal_type == 3:
132
+ header['board_adc_channels'].append(new_channel)
133
+ elif signal_type == 4:
134
+ header['board_dac_channels'].append(new_channel)
135
+ elif signal_type == 5:
136
+ header['board_dig_in_channels'].append(new_channel)
137
+ elif signal_type == 6:
138
+ header['board_dig_out_channels'].append(new_channel)
139
+ else:
140
+ raise Exception('Unknown channel type.')
141
+
142
+ # Summarize contents of data file.
143
+ header['num_amplifier_channels'] = len(header['amplifier_channels'])
144
+ header['num_board_adc_channels'] = len(header['board_adc_channels'])
145
+ header['num_board_dac_channels'] = len(header['board_dac_channels'])
146
+ header['num_board_dig_in_channels'] = len(header['board_dig_in_channels'])
147
+ header['num_board_dig_out_channels'] = len(header['board_dig_out_channels'])
148
+
149
+ return header
150
+
151
+ if __name__ == '__main__':
152
+ h=read_header(open(sys.argv[1], 'rb'))
153
+ print(h)
@@ -0,0 +1,47 @@
1
+ #! /bin/env python
2
+ #
3
+ # Michael Gibson 23 April 2015
4
+ # Modified Zeke Arneodo Dec 2017
5
+ # Modified Adrian Foy Sep 2018
6
+
7
+ import struct
8
+ import numpy as np
9
+
10
+
11
+ def read_one_data_block(data, header, indices, fid):
12
+ """Reads one 128-sample data block from fid into data, at the location indicated by indices."""
13
+
14
+ data['t'][indices['amplifier']:
15
+ (indices['amplifier']+128)] = np.array(struct.unpack('<' + 'i' * 128, fid.read(128*4)))
16
+
17
+ if header['num_amplifier_channels'] > 0:
18
+ tmp = np.fromfile(fid, dtype='uint16', count=128 * header['num_amplifier_channels'])
19
+ data['amplifier_data'][range(header['num_amplifier_channels']),
20
+ indices['amplifier']:(indices['amplifier']+128)] = tmp.reshape(header['num_amplifier_channels'], 128)
21
+
22
+ # check if dc amplifier voltage was saved
23
+ if header['dc_amplifier_data_saved']:
24
+ tmp = np.fromfile(fid, dtype='uint16', count=128 * header['num_amplifier_channels'])
25
+ data['dc_amplifier_data'][range(header['num_amplifier_channels']),
26
+ indices['amplifier']:(indices['amplifier'] + 128)] = tmp.reshape(header['num_amplifier_channels'], 128)
27
+
28
+ # get the stimulation data
29
+ tmp = np.fromfile(fid, dtype='uint16', count=128 * header['num_amplifier_channels'])
30
+ data['stim_data_raw'][range(header['num_amplifier_channels']),
31
+ indices['amplifier']:(indices['amplifier'] + 128)] = tmp.reshape(header['num_amplifier_channels'], 128)
32
+
33
+ if header['num_board_adc_channels'] > 0:
34
+ tmp = np.fromfile(fid, dtype='uint16', count=128 * header['num_board_adc_channels'])
35
+ data['board_adc_data'][range(header['num_board_adc_channels']),
36
+ indices['board_adc']:(indices['board_adc'] + 128)] = tmp.reshape(header['num_board_adc_channels'], 128)
37
+
38
+ if header['num_board_dac_channels'] > 0:
39
+ tmp = np.fromfile(fid, dtype='uint16', count=128 * header['num_board_dac_channels'])
40
+ data['board_dac_data'][range(header['num_board_dac_channels']),
41
+ indices['board_dac']:(indices['board_dac'] + 128)] = tmp.reshape(header['num_board_dac_channels'], 128)
42
+
43
+ if header['num_board_dig_in_channels'] > 0:
44
+ data['board_dig_in_raw'][indices['board_dig_in']:(indices['board_dig_in'] + 128)] = np.array(struct.unpack('<' + 'H' * 128, fid.read(256)))
45
+
46
+ if header['num_board_dig_out_channels'] > 0:
47
+ data['board_dig_out_raw'][indices['board_dig_out']:(indices['board_dig_out'] + 128)] = np.array(struct.unpack('<' + 'H' * 128, fid.read(256)))