binspikes.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """
  2. Arrange spike times into bins by stimulus frame times
  3. """
  4. from pathlib import Path
  5. import numpy as np
  6. import json
  7. __all__ = [
  8. 'binspikes',
  9. ]
  10. def binspikes(path):
  11. """
  12. Arrange spike times into bins by stimulus frame times
  13. Parameters
  14. ----------
  15. path : str or pathlib.Path
  16. Path to the data directory containing parameters, stimulus frame
  17. times, and spike times of all cells
  18. Returns
  19. -------
  20. runningbin : (k, r, c) numpy.ndarray
  21. Binned spikes for the non-repeating "running" stimulus parts,
  22. where k is the number of trials, r is the number of bins per
  23. part, and c is the number of cells
  24. frozenbin : (k, f, c) numpy.ndarray
  25. Binned spikes for the repeating "frozen" stimulus parts
  26. moviebin : (k, m, c) numpy.ndarray
  27. Binned spikes for the repeating "movie" stimulus parts. Only
  28. returned if the experiment contained the movie stimulation
  29. """
  30. # Load stimulus parameters from disk
  31. path = Path(path).expanduser()
  32. filepath = path/'parameters.json'
  33. p = json.loads(filepath.read_text())
  34. # Determine length (number of bins) of one trial
  35. len_run = p.setdefault('RunningFrames', 1500) * p['Nblinks']
  36. len_frz = p.setdefault('FrozenFrames', 0) * p['Nblinks']
  37. len_mov = p.setdefault('MovieFrames', 0) * p.setdefault('Nblinksmovie', 0)
  38. len_trial = len_run + len_frz + len_mov
  39. # Load stimulus frame times and spike times from disk
  40. ft_file = path/'frametimes.txt'
  41. sp_files = path.glob('spiketimes_cell*.txt')
  42. sp_files = sorted(sp_files, key=lambda x: int(x.name[15:-4])) # Sort files
  43. frametimes = np.loadtxt(ft_file)
  44. spiketimes = [np.loadtxt(file) for file in sp_files]
  45. num_cells = len(spiketimes)
  46. # Add the monitor delay to the stimulus frame times
  47. filepath = path/'../expdata.json'
  48. e = json.loads(filepath.read_text())
  49. frametimes += e['projector']['delay']
  50. # Check frame time frequency with respect to monitor refresh rate
  51. ftimes_freq = 1000 / (np.diff(frametimes).mean() * 1000)
  52. pulses = int(round(e['projector']['refreshrate'] / ftimes_freq))
  53. # Bin the spike times by stimulus frame times
  54. spkbin = np.zeros((frametimes.size * pulses, num_cells), dtype='uint8')
  55. frametimes_ext = np.append(frametimes, frametimes[-1]) # Add last bin edge
  56. for i in range(num_cells):
  57. spkbin[::pulses, i] = np.histogram(spiketimes[i], frametimes_ext)[0]
  58. # Reshape binned spikes by trial
  59. num_trials = int(frametimes.size*pulses / len_trial)
  60. total_len = num_trials * len_trial
  61. spkbin = spkbin[:total_len]
  62. spkbin = spkbin.reshape(num_trials, len_trial, num_cells)
  63. # Separate running and frozen parts
  64. runningbin = spkbin[:, :len_run, :]
  65. frozenbin = spkbin[:, len_run:len_run+len_frz, :]
  66. moviebin = spkbin[:, len_run+len_frz:, :]
  67. # Adjust bins to blinks
  68. shape_r = (num_trials, p['RunningFrames'], p['Nblinks'], num_cells)
  69. shape_f = (num_trials, p['FrozenFrames'], p['Nblinks'], num_cells)
  70. shape_m = (num_trials, p['MovieFrames'], p['Nblinksmovie'], num_cells)
  71. runningbin = runningbin.reshape(shape_r).sum(axis=2, dtype='uint8')
  72. frozenbin = frozenbin.reshape(shape_f).sum(axis=2, dtype='uint8')
  73. moviebin = moviebin.reshape(shape_m).sum(axis=2, dtype='uint8')
  74. if p['MovieFrames']:
  75. return runningbin, frozenbin, moviebin
  76. elif p['FrozenFrames']:
  77. return runningbin, frozenbin
  78. else:
  79. return runningbin, # Return tuple for consistency
  80. if __name__ == '__main__':
  81. print('\nThis file is a python module. Import it to call the function:')
  82. print(' >>> from binspikes import binspikes')
  83. print(' >>> path = \'20220208_60pMEA_right_i1/FrozenNoise_1/\'')
  84. print(' >>> runningbin, frozenbin = binspikes(path)\n')
  85. print('Details:')
  86. print(binspikes.__doc__)