1 """Compiled routines for sampled data.
2
3 Copyright 2008-2011 Research Foundation State University of New York
4 This file is part of QUB Express.
5
6 QUB Express is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 QUB Express is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License,
17 named LICENSE.txt, in the QUB Express program directory. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 """
21 from qubx.fast.fast_utils import *
22
23 qubfast.qub_raster_samples.argtypes = (c_int, c_int, c_float_p, c_double, c_double,
24 c_float_p, c_float_p, c_float_p, c_float_p)
25 qubfast.qub_raster_samples.restype = c_int
26
27
28
29
31 """
32 Returns (lows, highs, gauss_lows, gauss_highs); arrays of at most w y-coords;
33 each pixel represents several samples; the arrays give the minimum, maximum, and mean +/- one std.
34
35 @param resolution: min difference between highs[i] and lows[i]
36 """
37 def cdata(x, typ):
38 if x is None: return x
39 return x.ctypes.data_as(typ)
40 lows = numpy.zeros(shape=(w,), dtype='float32')
41 highs = numpy.zeros(shape=(w,), dtype='float32')
42 gauss_lows = numpy.zeros(shape=(w,), dtype='float32')
43 gauss_highs = numpy.zeros(shape=(w,), dtype='float32')
44 raster_count = qubfast.qub_raster_samples(w, len(samples), cdata(samples, c_float_p), samples_per_pixel, resolution,
45 cdata(lows, c_float_p), cdata(highs, c_float_p),
46 cdata(gauss_lows, c_float_p), cdata(gauss_highs, c_float_p))
47 return lows[:raster_count], highs[:raster_count], gauss_lows[:raster_count], gauss_highs[:raster_count]
48
49
50 qubfast.qub_doseresponse_equil_init.argtypes = (c_int,)
51 qubfast.qub_doseresponse_equil_init.restype = c_int_p
52 qubfast.qub_doseresponse_equil_free.argtypes = (c_int_p,)
53 qubfast.qub_doseresponse_equil_free.restype = None
54 qubfast.qub_doseresponse_equil_add_data.argtypes = (c_int_p, c_int, c_float_p, c_float_p)
55 qubfast.qub_doseresponse_equil_add_data.restype = None
56 qubfast.qub_doseresponse_equil_result.argtypes = (c_int_p, c_int, c_float_p, c_float_p, c_float_p)
57 qubfast.qub_doseresponse_equil_result.restype = c_int
58
60 """Very important to feed data chunks in reverse order."""
62 self.dr = qubfast.qub_doseresponse_equil_init(Ntail)
64 qubfast.qub_doseresponse_equil_free(self.dr)
66 qubfast.qub_doseresponse_equil_add_data(self.dr, min(len(stim), len(resp)), stim.ctypes.data_as(c_float_p), resp.ctypes.data_as(c_float_p))
67 - def result(self, max_results=100):
68 dose = numpy.zeros(shape=(max_results,), dtype='float32')
69 resp = numpy.zeros(shape=(max_results,), dtype='float32')
70 resp_std = numpy.zeros(shape=(max_results,), dtype='float32')
71 Nresult = qubfast.qub_doseresponse_equil_result(self.dr, max_results, dose.ctypes.data_as(c_float_p),
72 resp.ctypes.data_as(c_float_p), resp_std.ctypes.data_as(c_float_p))
73 return dose[:Nresult], resp[:Nresult], resp_std[:Nresult]
74
75 qubfast.qub_doseresponse_peak_init.argtypes = (c_double, c_double, c_double)
76 qubfast.qub_doseresponse_peak_init.restype = c_int_p
77 qubfast.qub_doseresponse_peak_free.argtypes = (c_int_p,)
78 qubfast.qub_doseresponse_peak_free.restype = None
79 qubfast.qub_doseresponse_peak_add_data.argtypes = (c_int_p, c_int, c_float_p, c_float_p)
80 qubfast.qub_doseresponse_peak_add_data.restype = None
81 qubfast.qub_doseresponse_peak_result.argtypes = (c_int_p, c_int, c_float_p, c_float_p)
82 qubfast.qub_doseresponse_peak_result.restype = c_int
83
85 """Feed whole segments please."""
86 - def __init__(self, sampling_sec, filter_kHz, sign):
89 qubfast.qub_doseresponse_peak_free(self.dr)
91 qubfast.qub_doseresponse_peak_add_data(self.dr, min(len(stim), len(resp)), stim.ctypes.data_as(c_float_p), resp.ctypes.data_as(c_float_p))
92 - def result(self, max_results=100):
93 dose = numpy.zeros(shape=(max_results,), dtype='float32')
94 resp = numpy.zeros(shape=(max_results,), dtype='float32')
95 Nresult = qubfast.qub_doseresponse_peak_result(self.dr, max_results, dose.ctypes.data_as(c_float_p),
96 resp.ctypes.data_as(c_float_p))
97 return dose[:Nresult], resp[:Nresult]
98
99
100 qubfast.qub_idlstim_create.argtypes = (c_double_p, c_int, c_int, c_double, c_double, c_double)
101 qubfast.qub_idlstim_create.restype = c_int_p
102 qubfast.qub_idlstim_destroy.argtypes = (c_int_p,)
103 qubfast.qub_idlstim_destroy.restype = None
104 qubfast.qub_idlstim_add.argtypes = (c_int_p, c_float_p, c_int)
105 qubfast.qub_idlstim_add.restype = None
106 qubfast.qub_idlstim_done_add.argtypes = (c_int_p,)
107 qubfast.qub_idlstim_done_add.restype = None
108 qubfast.qub_idlstim_get_amp_count.argtypes = (c_int_p,)
109 qubfast.qub_idlstim_get_amp_count.restype = c_int
110 qubfast.qub_idlstim_get_amps.argtypes = (c_int_p, c_double_p)
111 qubfast.qub_idlstim_get_amps.restype = c_int
112 qubfast.qub_idlstim_get_next_dwells.argtypes = (c_int_p, c_int, c_int, c_int_p, c_int_p, c_int_p, c_float_p)
113 qubfast.qub_idlstim_get_next_dwells.restype = c_int
114
116 """Idealizes a stimulus signal.
117 """
118 - def __init__(self, known_amps, add_deltas, delta, min_dur_ms, sampling_ms):
119 """
120 @param known_amps: list of known stimulus levels
121 @param add_deltas: True if the idealizer can find new levels
122 @param delta: minimum difference between found levels
123 @param min_dur_ms: dwells shorter than this will be joined to a neighbor
124 @param sampling_ms: sampling interval in milliseconds
125 """
126 amps = numpy.array(known_amps, dtype='float64')
127 self.idlstim = qubfast.qub_idlstim_create(amps.ctypes.data_as(c_double_p), len(amps), add_deltas, delta, min_dur_ms, sampling_ms)
129 qubfast.qub_idlstim_destroy(self.idlstim)
130 - def add(self, samples):
131 """Feeds in a numpy.array(dtype=float32) of samples; you add all samples, then call done_add, then for each array of samples added, you call get_next_dwells."""
132 qubfast.qub_idlstim_add(self.idlstim, samples.ctypes.data_as(c_float_p), len(samples))
134 """Indicates you're done calling add(), so it can prepare the final amps and dwells."""
135 qubfast.qub_idlstim_done_add(self.idlstim)
137 """After you've called done_add(), returns the amp of each class in the output."""
138 amps = numpy.zeros(shape=(qubfast.qub_idlstim_get_amp_count(self.idlstim),), dtype='float64')
139 qubfast.qub_idlstim_get_amps(self.idlstim, amps.ctypes.data_as(c_double_p))
140 return amps
141 - def get_next_dwells(self, offset_in_data, sample_count, get_durations=False):
142 """After you've called done_add(), call this once for each array of samples you added.
143
144 @param offset_in_data: the "first" sample index for the source sample array
145 @param sample_count: length of the source array
146 @param get_durations: whether to return an array of durations
147 @returns: (firsts, lasts, classes[, durations])
148 """
149 firsts = numpy.zeros(shape=(sample_count,), dtype='int32')
150 lasts = numpy.zeros(shape=(sample_count,), dtype='int32')
151 classes = numpy.zeros(shape=(sample_count,), dtype='int32')
152 if get_durations:
153 durations = numpy.zeros(shape=(sample_count,), dtype='float32')
154 dd = durations.ctypes.data_as(c_float_p)
155 else:
156 dd = None
157 ndwt = qubfast.qub_idlstim_get_next_dwells(self.idlstim, offset_in_data, sample_count,
158 firsts.ctypes.data_as(c_int_p),
159 lasts.ctypes.data_as(c_int_p),
160 classes.ctypes.data_as(c_int_p),
161 dd)
162 if get_durations:
163 return numpy.array(firsts[:ndwt]), numpy.array(lasts[:ndwt]), numpy.array(classes[:ndwt]), numpy.array(durations[:ndwt])
164 else:
165 return numpy.array(firsts[:ndwt]), numpy.array(lasts[:ndwt]), numpy.array(classes[:ndwt])
166
167
168
169 qubfast.qub_adaptive_resample.argtypes = (c_float_p, c_int, c_double, c_float_p, c_float_p, c_int_p, c_int_p, c_int_p)
170 qubfast.qub_adaptive_resample.restype = c_int
171
172
173
174
175
177 """
178 Divides samples into intervals such that all(stds[i] < max_std). Also finds the closest sample to the mean in each interval.
179
180 @param samples: numpy.array(float32) of sampled data
181 @param max_std: desired ceiling for all stds[i]
182 @returns: (means, stds, firsts, lasts, closests) -- array[interval_index]
183 """
184 def cdata(x, typ):
185 if x is None: return x
186 return x.ctypes.data_as(typ)
187 ndata = samples.shape[0]
188 out_means = numpy.zeros(shape=(ndata,), dtype='float32')
189 out_stds = numpy.zeros(shape=(ndata,), dtype='float32')
190 out_firsts = numpy.zeros(shape=(ndata,), dtype='int32')
191 out_lasts = numpy.zeros(shape=(ndata,), dtype='int32')
192 out_closests = numpy.zeros(shape=(ndata,), dtype='int32')
193 out_count = qubfast.qub_adaptive_resample(cdata(samples, c_float_p), ndata, max_std,
194 cdata(out_means, c_float_p), cdata(out_stds, c_float_p),
195 cdata(out_firsts, c_int_p), cdata(out_lasts, c_int_p),
196 cdata(out_closests, c_int_p))
197 return (numpy.array(out_means[:out_count]),
198 numpy.array(out_stds[:out_count]),
199 numpy.array(out_firsts[:out_count]),
200 numpy.array(out_lasts[:out_count]),
201 numpy.array(out_closests[:out_count]))
202
203
204 qubfast.qub_adres_create.argtypes = (c_double, c_double, c_double)
205 qubfast.qub_adres_create.restype = c_int_p
206 qubfast.qub_adres_destroy.argtypes = (c_int_p,)
207 qubfast.qub_adres_destroy.restype = None
208 qubfast.qub_adres_add.argtypes = (c_int_p, c_float_p, c_int)
209 qubfast.qub_adres_add.restype = None
210 qubfast.qub_adres_done_add.argtypes = (c_int_p,)
211 qubfast.qub_adres_done_add.restype = None
212 qubfast.qub_adres_get_class_count.argtypes = (c_int_p,)
213 qubfast.qub_adres_get_class_count.restype = c_int
214 qubfast.qub_adres_get_dist.argtypes = (c_int_p, c_double_p, c_double_p)
215 qubfast.qub_adres_get_dist.restype = c_int
216 qubfast.qub_adres_get_next_dwells.argtypes = (c_int_p, c_int, c_int, c_int_p, c_int_p, c_int_p, c_float_p)
217 qubfast.qub_adres_get_next_dwells.restype = c_int
218
220 """Idealizes a stimulus signal.
221 """
222 - def __init__(self, delta, min_dur_ms, sampling_ms):
223 """
224 @param delta: minimum difference between found levels
225 @param min_dur_ms: dwells shorter than this will be joined to a neighbor
226 @param sampling_ms: sampling interval in milliseconds
227 """
228 self.adres = qubfast.qub_adres_create(delta, min_dur_ms, sampling_ms)
230 qubfast.qub_adres_destroy(self.adres)
231 - def add(self, samples):
232 """Feeds in a numpy.array(dtype=float32) of samples; you add all samples, then call done_add, then for each array of samples added, you call get_next_dwells."""
233 qubfast.qub_adres_add(self.adres, samples.ctypes.data_as(c_float_p), len(samples))
235 """Indicates you're done calling add(), so it can prepare the final amps and dwells."""
236 qubfast.qub_adres_done_add(self.adres)
238 """After you've called done_add(), returns the (amps, stds)."""
239 n = qubfast.qub_adres_get_class_count(self.adres)
240 amps = numpy.zeros(shape=(n,), dtype='float64')
241 stds = numpy.zeros(shape=(n,), dtype='float64')
242 qubfast.qub_adres_get_dist(self.adres, amps.ctypes.data_as(c_double_p), stds.ctypes.data_as(c_double_p))
243 return amps, stds
244 - def get_next_dwells(self, offset_in_data, sample_count, get_durations=False):
245 """After you've called done_add(), call this once for each array of samples you added.
246
247 @param offset_in_data: the "first" sample index for the source sample array
248 @param sample_count: length of the source array
249 @param get_durations: whether to return an array of durations
250 @returns: (firsts, lasts, classes[, durations])
251 """
252 firsts = numpy.zeros(shape=(sample_count,), dtype='int32')
253 lasts = numpy.zeros(shape=(sample_count,), dtype='int32')
254 classes = numpy.zeros(shape=(sample_count,), dtype='int32')
255 if get_durations:
256 durations = numpy.zeros(shape=(sample_count,), dtype='float32')
257 dd = durations.ctypes.data_as(c_float_p)
258 else:
259 dd = None
260 ndwt = qubfast.qub_adres_get_next_dwells(self.adres, offset_in_data, sample_count,
261 firsts.ctypes.data_as(c_int_p),
262 lasts.ctypes.data_as(c_int_p),
263 classes.ctypes.data_as(c_int_p),
264 dd)
265 if get_durations:
266 return numpy.array(firsts[:ndwt]), numpy.array(lasts[:ndwt]), numpy.array(classes[:ndwt]), numpy.array(durations[:ndwt])
267 else:
268 return numpy.array(firsts[:ndwt]), numpy.array(lasts[:ndwt]), numpy.array(classes[:ndwt])
269
270
271
272
273 qubfast.decode_acquirefile_samples.argtypes = (c_char_p, c_short_p, c_int, c_int)
274 qubfast.decode_acquirefile_samples.restype = None
275
278
279
280
281 qubfast.qub_idlstats_create.argtypes = (c_double,)
282 qubfast.qub_idlstats_create.restype = c_void_p
283 qubfast.qub_idlstats_free.argtypes = (c_void_p,)
284 qubfast.qub_idlstats_free.restype = None
285 qubfast.qub_idlstats_reset.argtypes = (c_void_p,)
286 qubfast.qub_idlstats_reset.restype = None
287 qubfast.qub_idlstats_add.argtypes = (c_void_p, c_float_p, c_int, c_int, c_int_p, c_int_p, c_int_p)
288 qubfast.qub_idlstats_add.restype = None
289 qubfast.qub_idlstats_add_up_means.argtypes = (c_void_p,)
290 qubfast.qub_idlstats_add_up_means.restype = c_int
291 qubfast.qub_idlstats_get_means.argtypes = (c_void_p,)
292 qubfast.qub_idlstats_get_means.restype = c_double_p
293 qubfast.qub_idlstats_get_lifetimes.argtypes = (c_void_p,)
294 qubfast.qub_idlstats_get_lifetimes.restype = c_double_p
295 qubfast.qub_idlstats_get_median_lifetimes.argtypes = (c_void_p,)
296 qubfast.qub_idlstats_get_median_lifetimes.restype = c_double_p
297 qubfast.qub_idlstats_get_occupancies.argtypes = (c_void_p,)
298 qubfast.qub_idlstats_get_occupancies.restype = c_double_p
299 qubfast.qub_idlstats_get_nevents.argtypes = (c_void_p,)
300 qubfast.qub_idlstats_get_nevents.restype = c_int_p
301 qubfast.qub_idlstats_add_up_stds.argtypes = (c_void_p,)
302 qubfast.qub_idlstats_add_up_stds.restype = c_int
303 qubfast.qub_idlstats_get_stds.argtypes = (c_void_p,)
304 qubfast.qub_idlstats_get_stds.restype = c_double_p
305
314 - def add(self, data, offset, firsts, lasts, classes):
315
316 if len(firsts):
317 qubfast.qub_idlstats_add(self.obj, cdata(data, c_float_p), len(firsts), offset,
318 cdata(firsts, c_int_p), cdata(lasts, c_int_p), cdata(classes, c_int_p))
333 return qubfast.qub_idlstats_add_up_stds(self.obj)
336
337
338 qubfast.qub_mean_rss.argtypes = (c_float_p, c_int, c_double_p, c_double_p)
339 qubfast.qub_mean_rss.restype = None
340 qubfast.qub_mean_rss_init.argtypes = (c_float_p, c_int, c_double_p, c_double_p)
341 qubfast.qub_mean_rss_init.restype = c_void_p
342 qubfast.qub_mean_rss_free.argtypes = (c_void_p,)
343 qubfast.qub_mean_rss_free.restype = None
344 qubfast.qub_mean_rss_add.argtypes = (c_void_p, c_float_p, c_int)
345 qubfast.qub_mean_rss_add.restype = None
346 qubfast.qub_mean_rss_read.argtypes = (c_void_p, c_double_p, c_double_p)
347 qubfast.qub_mean_rss_read.restype = c_int
348
358
375