|
| 1 | +Working with physical units in SpikeInterface recordings |
| 2 | +======================================================== |
| 3 | + |
| 4 | +In neurophysiology recordings, data is often stored in raw ADC (Analog-to-Digital Converter) integer values but needs to be analyzed in physical units. |
| 5 | +For extracellular recordings, this is typically microvolts (µV), but some recording devices may use different physical units. |
| 6 | +SpikeInterface provides tools to handle both situations. |
| 7 | + |
| 8 | +It's important to note that **most spike sorters work fine on raw digital (ADC) units** and scaling is not needed. Going a step further, some sorters, such as Kilosort 3, require their input to be in raw ADC units. |
| 9 | +The specific behavior however depends on the spike sorter, so it's important to understand the specific input requirements on a case per case basis. |
| 10 | + |
| 11 | +Many preprocessing tools are also linear transformations, and if the ADC is implemented as a linear transformation which is fairly common, then the overall effect can be preserved. |
| 12 | +That is, **preprocessing steps can often be applied either before or after unit conversion without affecting the outcome.**. That being said, there are rough edges to this approach. |
| 13 | +preprocessing algorithms like filtering, whitening, centering, interpolation and common reference require casting to float within the pipeline. We advise users to experiment |
| 14 | +with different approaches to find the best one for their specific use case. |
| 15 | + |
| 16 | + |
| 17 | +Therefore, **it is usually safe to work in raw ADC integer values unless a specific tool or analysis requires physical units**. |
| 18 | +If you are interested in visualizations, comparability across devices, or outputs with interpretable physical scales (e.g., microvolts), converting to physical units is recommended. |
| 19 | +Otherwise, remaining in raw units can simplify processing and preserve performance. |
| 20 | + |
| 21 | +Understanding Physical Units |
| 22 | +---------------------------- |
| 23 | + |
| 24 | +Most recording devices store data in ADC units (integers) to save space and preserve the raw data. |
| 25 | +To convert these values to physical units, two parameters are needed: |
| 26 | + |
| 27 | +* **gain**: A multiplicative factor to scale the raw values |
| 28 | +* **offset**: An additive factor to shift the values |
| 29 | + |
| 30 | +The conversion formula is: |
| 31 | + |
| 32 | +.. code-block:: text |
| 33 | +
|
| 34 | + physical_value = raw_value * gain + offset |
| 35 | +
|
| 36 | +
|
| 37 | +Converting to Physical Units |
| 38 | +---------------------------- |
| 39 | + |
| 40 | +SpikeInterface provides two preprocessing classes for converting recordings to physical units. Both wrap the |
| 41 | +``RecordingExtractor`` class and ensures that the data is returned in physical units when calling `get_traces <https://spikeinterface.readthedocs.io/en/stable/api.html#spikeinterface.core.BaseRecording.get_traces>`_ |
| 42 | + |
| 43 | +1. ``scale_to_uV``: The primary function for extracellular recordings. SpikeInterface is centered around |
| 44 | + extracellular recordings, and this function is designed to convert the data to microvolts (µV). |
| 45 | +2. ``scale_to_physical_units``: A general function for any physical unit conversion. This will allow you to extract the data in any |
| 46 | + physical unit, not just microvolts. This is useful for other types of recordings, such as force measurements in Newtons but should be |
| 47 | + handled with care. |
| 48 | + |
| 49 | +For most users working with extracellular recordings, ``scale_to_uV`` is the recommended choice if they want to work in physical units: |
| 50 | + |
| 51 | +.. code-block:: python |
| 52 | +
|
| 53 | + from spikeinterface.extractors import read_intan |
| 54 | + from spikeinterface.preprocessing import scale_to_uV |
| 55 | +
|
| 56 | + # Load recording (data is in ADC units) |
| 57 | + recording = read_intan("path/to/file.rhs") |
| 58 | +
|
| 59 | + # Convert to microvolts |
| 60 | + recording_uv = scale_to_uV(recording) |
| 61 | +
|
| 62 | +For recordings with non-standard units (e.g., force measurements in Newtons), use ``scale_to_physical_units``: |
| 63 | + |
| 64 | +.. code-block:: python |
| 65 | +
|
| 66 | + from spikeinterface.preprocessing import scale_to_physical_units |
| 67 | +
|
| 68 | + # Convert to physical units (whatever they may be) |
| 69 | + recording_physical = scale_to_physical_units(recording) |
| 70 | +
|
| 71 | +Both preprocessors automatically: |
| 72 | + |
| 73 | +1. Detect the appropriate gain and offset from the recording properties |
| 74 | +2. Apply the conversion to all channels |
| 75 | +3. Update the recording properties to reflect that data is now in physical units |
| 76 | + |
| 77 | +Setting Custom Physical Units |
| 78 | +----------------------------- |
| 79 | + |
| 80 | +While most extractors automatically set the appropriate ``gain_to_uV`` and ``offset_to_uV`` values, |
| 81 | +there might be cases where you want to set custom physical units. In these cases, you can set |
| 82 | +the following properties: |
| 83 | + |
| 84 | +* ``physical_unit``: The target physical unit (e.g., 'uV', 'mV', 'N') |
| 85 | +* ``gain_to_unit``: The gain to convert from raw values to the target unit |
| 86 | +* ``offset_to_unit``: The offset to convert from raw values to the target unit |
| 87 | + |
| 88 | +You need to set these properties for every channel, which allows for the case when there are different gains and offsets on different channels. Here's an example: |
| 89 | + |
| 90 | +.. code-block:: python |
| 91 | +
|
| 92 | + # Set custom physical units |
| 93 | + num_channels = recording.get_num_channels() |
| 94 | + values = ["volts"] * num_channels |
| 95 | + recording.set_property(key='physical_unit', values=values) |
| 96 | +
|
| 97 | + gain_values = [0.001] * num_channels # Convert from ADC to volts |
| 98 | + recording.set_property(key='gain_to_unit', values=gain_values) # Convert to volts |
| 99 | +
|
| 100 | + offset_values = [0] * num_channels # No offset |
| 101 | + recording.set_property(key='offset_to_unit', values=offset_values) # No offset |
| 102 | +
|
| 103 | + # Apply the conversion using scale_to_physical_units |
| 104 | + recording_physical = scale_to_physical_units(recording) |
| 105 | +
|
| 106 | +This approach gives you full control over the unit conversion process while maintaining |
| 107 | +compatibility with SpikeInterface's preprocessing pipeline. |
0 commit comments