Skip to content

ndi.fun.export.gmcSorterWrite

  NDI.FUN.EXPORT.GMCSORTERWRITE - write in-memory voltage to GMC_Sorter's 'dat_t_s' raw format

  NDI.FUN.EXPORT.GMCSORTERWRITE(OUTPUTFOLDER, SAMPLES, TIMESTAMPS, CHANNELPOSITIONS, ...)

  Writes a recording held in memory to the raw file format that GMC_Sorter
  (https://github.com/stevevanhooser/GMC_Sorter) reads as file_struct
  'dat_t_s'. This is the pure, session-free core used by
  NDI.FUN.EXPORT.GMCSORTER; it takes plain arrays so it can be unit-tested
  without an NDI session or DAQ (see gmcSorterWriteTest).

  INPUTS
  --------------------------------------------------------------------------
  | SAMPLES           | n_channels x n_samples voltage. Written as int16.   |
  |                   |   Column j (all channels of sample j) is written    |
  |                   |   contiguously, so on disk the layout is            |
  |                   |   [ch0_s0, ch1_s0, ..., chN_s0, ch0_s1, ...] -- the |
  |                   |   exact interleaving raw_data.py reshapes as        |
  |                   |   (n_time_samples, n_saved_chans).                  |
  | TIMESTAMPS        | 1 x n_samples sample times in SECONDS. Written as    |
  |                   |   int64 MICROSECONDS (round(t*1e6)). Must be         |
  |                   |   monotonically increasing (raw_data.py binary-     |
  |                   |   searches them).                                   |
  | CHANNELPOSITIONS  | n_channels x 2 array of [x y] electrode positions   |
  |                   |   (microns), in the same channel order as SAMPLES.  |
  --------------------------------------------------------------------------

  The sidecars and the generated driver target GMC_Sorter Version 4: pass
  'shankIndex' for a multi-shank probe and the driver runs one
  extract_spike_features(..., ch_order=...) pass per shank, as GMC_Sorter's
  own main.py does. See NDI.FUN.EXPORT.WRITEGMCSIDECARS.

  The two '.dat' files are written little-endian (matching raw_data.py's
  native-endian numpy reads on x86). GMC_Sorter derives from their sizes:
    n_time_samples = sizeof(timestamps)/8 (int64)
    n_saved_chans  = sizeof(samples)/(n_time_samples*2) (int16)
    sample_rate    = 1e6 / median(diff(first 1000 timestamps))
  so the two files must agree on n_samples and n_channels.

  Files written into OUTPUTFOLDER:
    [baseName]_samples.dat       int16, channel-interleaved (see above)
    [baseName]_timestamps.dat    int64, microseconds
    channel_positions.csv, channel_map.mat, [baseName].metadata,
    run_gmc_extract.py           (via ndi.fun.export.writeGmcSidecars)

  Name/value pairs:
  --------------------------------------------------------------------------
  | Parameter (default)   | Description                                     |
  |-----------------------|-------------------------------------------------|
  | baseName ('RawData')  | Base name for the '.dat' pair and metadata.     |
  | multiplier (1)        | Encode multiplier: int16 = round(multiplier *   |
  |                       |   SAMPLES). Use to scale physical units into a  |
  |                       |   sensible int16 range without clipping (cf.    |
  |                       |   ndi.fun.probe.export.autoMultiplier). Values  |
  |                       |   are saturated to [-32768, 32767].             |
  | sampleRate ([])       | Representative sample rate (Hz) for metadata /  |
  |                       |   driver. If empty, inferred from TIMESTAMPS.   |
  | probeName ('')        | Probe elementstring recorded in the metadata.   |
  | writeSidecars (true)  | Write channel map / metadata / driver too.      |
  | shankIndex ([])       | n_channels x 1 shank id per channel; one        |
  |                       |   GMC_Sorter pass runs per distinct id. Empty   |
  |                       |   => a single shank.                            |
  | connected ([])        | n_channels x 1 logical; false channels are      |
  |                       |   written but left out of the driver's ch_order.|
  | sortByDepth (true)    | Order each shank's ch_order tip-to-base.        |
  | gmcProbeName ('')     | Use GMC_Sorter's probe_mappings wiring for this |
  |                       |   named probe instead of the exported table.    |
  | featureOptions ({})   | Name/value cell forwarded to                    |
  |                       |   extract_spike_features as keyword arguments.  |
  | makePlots (false)     | make_plots for extract_spike_features.          |
  | gmcSorterPath ('')    | Path to the GMC_Sorter checkout for the driver. |
  | verbose (1)           | 0/1 Should we be verbose?                       |
  --------------------------------------------------------------------------

  Example:
    fs = 30000; t = (0:2999)/fs;                 % 3000 samples, 100 ms
    x = int16(1000*randn(4,3000));               % 4 channels
    pos = [0 0; 0 25; 0 50; 0 75];               % linear, 25 um spacing
    ndi.fun.export.gmcSorterWrite('/tmp/rec', x, t, pos, 'baseName','RawData');

  See also: NDI.FUN.EXPORT.GMCSORTER, NDI.FUN.EXPORT.WRITEGMCSIDECARS,
    NDI.FUN.PROBE.EXPORT.BINARY