root/trunk/src/analysis.py

Revision 188, 4.2 kB (checked in by apdavison, 2 months ago)

* Added some __str__() methods
* time_bin can now be a list of bin edges instead of a numerical value.

Line 
1 #!/usr/bin/env python
2 # -*- coding: utf8 -*-
3 """
4 analysis.py:
5
6 $Id$
7 """
8
9 import os, numpy
10
11
12 def record(output, cfilename = 'SpikeTrainPlay.wav', fs=44100, enc = 'pcm26'):
13     """ record the 'sound' produced by a neuron. Takes a spike train as the
14     output.
15
16     >>> record(my_spike_train)
17
18     """
19
20
21     # from the spike list
22     simtime_seconds = (output.t_stop - output.t_start)/1000.
23     #time = numpy.linspace(0, simtime_seconds , fs*simtime_seconds)
24     (trace,time) = numpy.histogram(output.spike_times*1000., fs*simtime_seconds)
25
26
27     # TODO convolve with proper spike...
28     spike = numpy.ones((fs/1000.,)) # one ms
29
30     trace = numpy.convolve(trace, spike, mode='same')#/2.0
31     trace /= numpy.abs(trace).max() * 1.1
32
33     from scikits.audiolab import wavwrite
34     wavwrite(trace, cfilename, fs = fs, enc = enc)
35
36 def play(output):
37     """
38     plays a spike list to the audio output
39
40     play(spike_list) where spike_list is a spike_list object
41
42     see playing_with_simple_single_neuron.py for a sample use
43
44     >>> play(my_spike_train)
45
46     TODO: make it possible to play multiple spike trains in stereo
47     """
48
49
50     from tempfile import mkstemp
51     fd, cfilename   = mkstemp('SpikeListPlay.wav')
52     try:
53         record(output, cfilename)
54         import pyaudio
55         import wave
56
57         chunk = 1024
58         wf = wave.open(cfilename, 'rb')
59         p = pyaudio.PyAudio()
60
61         # open stream
62         stream = p.open(format =
63                         p.get_format_from_width(wf.getsampwidth()),
64                         channels = wf.getnchannels(),
65                         rate = wf.getframerate(),
66                         output = True)
67
68         # read data
69         data = wf.readframes(chunk)
70
71         # play stream
72         while data != '':
73             stream.write(data)
74             data = wf.readframes(chunk)
75
76         stream.close()
77         p.terminate()
78     except:
79         print "Error playing the SpikeTrain "
80         # finally
81         os.remove(cfilename)
82
83     # Python 2.4 compatibility
84     # finally:
85     os.remove(cfilename)
86
87 def _dict_max(D):
88     """
89     For a dict containing numerical values, contain the key for the
90     highest value. If there is more than one item with the same highest
91     value, return one of them (arbitrary - depends on the order produced
92     by the iterator).
93     """
94     max_val = max(D.values())
95     for k in D:
96         if D[k] == max_val:
97             return k
98        
99 def simple_frequency_spectrum(x):
100     """
101     Very simple calculation of frequency spectrum with no detrending,
102     windowing, etc. Just the first half (positive frequency components) of
103     abs(fft(x))
104     """
105     spec = numpy.absolute(numpy.fft.fft(x))
106     spec = spec[:len(x)/2] # take positive frequency components
107     spec /= len(x)         # normalize
108     spec *= 2.0            # to get amplitudes of sine components, need to multiply by 2
109     spec[0] /= 2.0         # except for the dc component
110     return spec
111
112 class TuningCurve(object):
113     """Class to facilitate working with tuning curves."""
114
115     def __init__(self, D=None):
116         """
117         If `D` is a dict, it is used to give initial values to the tuning curve.
118         """
119         self._tuning_curves = {}
120         self._counts = {}
121         if D is not None:
122             for k,v in D.items():
123                 self._tuning_curves[k] = [v]
124                 self._counts[k] = 1
125                 self.n = 1
126         else:
127             self.n = 0
128
129     def add(self, D):
130         for k,v  in D.items():
131             self._tuning_curves[k].append(v)
132             self._counts[k] += 1
133         self.n += 1
134
135     def __getitem__(self, i):
136         D = {}
137         for k,v in self._tuning_curves[k].items():
138             D[k] = v[i]
139         return D
140    
141     def __repr__(self):
142         return "TuningCurve: %s" % self._tuning_curves
143
144     def stats(self):
145         """Return the mean tuning curve with stderrs."""
146         mean = {}
147         stderr = {}
148         n = self.n
149         for k in self._tuning_curves.keys():
150             arr = numpy.array(self._tuning_curves[k])
151             mean[k] = arr.mean()
152             stderr[k] = arr.std()*n/(n-1)/numpy.sqrt(n)
153         return mean, stderr
154
155     def max(self):
156         """Return the key of the max value and the max value."""
157         k = _dict_max(self._tuning_curves)
158         return k, self._tuning_curves[k]
Note: See TracBrowser for help on using the browser.