def calc_max_repeats(self): ''' Returns maximum number of repeats of any one task in the dataset. Determines the shape of the sorted data arrays. Returns ------- max_reps : int maximum number of repeats of any one direction in center out ''' n_trials = self.HoldAStart.size n_dirs = self.tasks.shape[0] dirs_count = np.zeros(n_dirs, dtype=int) # step over trials for i in xrange(n_trials): dir_idx = tc_util.get_task_idx(self.StartPos[i], self.TargetPos[i], self.tasks) dirs_count[dir_idx] += 1 return dirs_count.max()
def make_binned(self, nbin=100, align='speed', verbose=False, do_count=True, do_rate=False): '''Constructs aligned PSTHs of spikes in each direction. Histograms are constructed with `n_bins`, aligned at increasing and decreasing 15% speed points, windowed to include maximum common period back to latest HoldAStart and up to earliest HoldBFinish. Parameters ---------- n_bins : int, default=100 number of bins align : string one of 'speed', 'hold', '3:2:3' verbose : bool print information messages? Returns ------- binned : BinnedData instance bd.PSTHs.shape = (n_tasks, n_reps, n_dsets, nbins) bd.pos.shape = (n_tasks, n_reps, nbins + 1, 3) ''' #assert len(self.units) > 0 assert type(nbin) == int assert align in align_types align_starts, align_stops, bin_starts, bin_stops = \ self._get_limits(align) do_spike = (do_count or do_rate) # sort n_trials trials into n_dirs directions # requires calc max_n_repeats per direction to construct array max_repeat = self.calc_max_repeats() ntrial = bin_starts.size ndir = self.tasks.shape[0] nunit = len(self.units) if (nunit > 0) and do_spike: if do_count: counts = np.empty((ndir, max_repeat, nunit, nbin)) + np.nan if do_rate: rates = np.empty((ndir, max_repeat, nunit, nbin)) + np.nan else: rates = None else: counts = None rates = None bin_edges = np.empty((ndir, max_repeat, nbin + 1)) + np.nan dirs_count = np.zeros(ndir) pos = np.empty((ndir, max_repeat, nbin + 1, 3)) + np.nan align_start_bins = None align_stop_bins = None for i in xrange(ntrial): # directions are sorted according to the sorted unique tasks if np.isnan(bin_starts[i]) or np.isnan(bin_stops[i]): # couldn't align trial for some reason- ignore if verbose: print "Sort error, trial %d: " \ "couldn't find alignment points." \ % i continue # put index of this trial into correct direction column dir_idx = tc_util.get_task_idx( \ self.StartPos[i], self.TargetPos[i], self.tasks) bins = np.linspace(bin_starts[i], bin_stops[i], nbin + 1, \ endpoint=True) if (nunit > 0) & do_spike: if do_count: trial_count = np.empty((nunit, nbin)) + np.nan if do_rate: trial_rate = np.empty((nunit, nbin)) + np.nan for i_unit, unit in enumerate(self.units): spikes = np.asarray(unit.spikes[i]) if do_count: trial_count[i_unit], _ = np.histogram(spikes, bins=bins) if do_rate: trial_rate[i_unit], _ = tc_util.unbiased_histogram( \ np.asarray(unit.spikes[i]), bins=bins) # interpolate position these_pos = _interpolate_position(self.positions[i], bins) # calculate (for display purposes later on) position of 15%-acc. # in bin numbers - should be constant, but not integer, for each bin_width = bins[1] - bins[0] this_align_start = (align_starts[i] - bin_starts[i]) / bin_width if align_start_bins != None: assert np.allclose(this_align_start, align_start_bins) align_start_bins = this_align_start this_align_stop = (align_stops[i] - bin_starts[i]) / bin_width if align_stop_bins != None: assert np.allclose(this_align_stop, align_stop_bins) align_end_bins = this_align_stop # tests here okay = True max_pos_threshold = 0.1 # 10 cm min_time_threshold = 0.05 # 50 ms if np.any(np.abs(these_pos) > max_pos_threshold): warn(AlignmentWarning("trial %d: position value too big" % i)) okay = False if (align_stops[i] - align_starts[i]) < min_time_threshold: warn(AlignmentWarning("trial %d: movement time too short" % i)) okay = False # if passed tests, add to collection if okay: rep_idx = dirs_count[dir_idx] if nunit > 0: if do_count: counts[dir_idx, rep_idx] = trial_count if do_rate: rates[dir_idx, rep_idx] = trial_rate bin_edges[dir_idx, rep_idx] = bins pos[dir_idx, rep_idx] = these_pos dirs_count[dir_idx] += 1 #... keep track of next row to enter for this direction unit_names = [u.unit_name for u in self.units] lags = [u.lag for u in self.units] return BinnedData(bin_edges, pos, self.tasks, unit_names, align, lags=lags, count=counts, unbiased_rate=rates, align_start_bins=align_start_bins, align_end_bins=align_end_bins, files=self.files)