def get_TR_offset_stats(self, tr): """create a list of TR offsets (per-run and overall) tr : must be positive return: 8 values in a list: min, mean, maxabs, stdev of absolute and fractional offsets empty list on error """ if not self.ready: print('** M Timing: nothing to compute ISI stats from') return [] if self.nrows != len(self.data): print('** bad MTiming, nrows=%d, datalen=%d, failing...' % \ (self.nrows, len(self.data))) return [] if tr < 0.0: print('** show_TR_offset_stats: invalid TR %s' % tr) return [] tr = float(tr) # to be sure # make a copy of format run x stim x [start,end], i.e. is 3-D tdata = self.get_start_end_timing() offsets = [] # stim offsets within given TRs for rind in range(self.nrows): run = tdata[rind] if len(run) == 0: continue roffsets = UTIL.interval_offsets([val[0] for val in run], tr) offsets.extend(roffsets) if len(offsets) < 1: return [] # get overall stats (absolute and fractional) # absolute m0, m1, m2, s = UTIL.min_mean_max_stdev(offsets) offmn = m0 offm = m1 offs = s mn = abs(min(offsets)) offmax = abs(max(offsets)) if mn > offmax: offmax = mn # fractional for ind, val in enumerate(offsets): offsets[ind] = val / tr m0, m1, m2, s = UTIL.min_mean_max_stdev(offsets) del (offsets) return [offmn, offm, offmax, offs, m0, m1, offmax / tr, s]
def get_TR_offset_stats(self, tr): """create a list of TR offsets (per-run and overall) tr : must be positive return: 8 values in a list: min, mean, maxabs, stdev of absolute and fractional offsets empty list on error """ if not self.ready: print '** M Timing: nothing to compute ISI stats from' return [] if self.nrows != len(self.data): print '** bad MTiming, nrows=%d, datalen=%d, failing...' % \ (self.nrows, len(self.data)) return [] if tr < 0.0: print '** show_TR_offset_stats: invalid TR %s' % tr return [] # make a copy of format run x stim x [start,end], i.e. is 3-D tdata = self.get_start_end_timing() offsets = [] # stim offsets within given TRs for rind in range(self.nrows): run = tdata[rind] if len(run) == 0: continue roffsets = UTIL.interval_offsets([val[0] for val in run], tr) offsets.extend(roffsets) if len(offsets) < 1: return [] # get overall stats (absolute and fractional) # absolute m0, m1, m2, s = UTIL.min_mean_max_stdev(offsets) offmn = m0; offm = m1; offs = s mn = abs(min(offsets)) offmax = abs(max(offsets)) if mn > offmax: offmax = mn # fractional for ind, val in enumerate(offsets): offsets[ind] = val/tr m0, m1, m2, s = UTIL.min_mean_max_stdev(offsets) del(offsets) return [offmn, offm, offmax, offs, m0, m1, offmax/tr, s]
def show_durlist_stats(self, mesg='', details=0): tc = self.sclass durlist = self.durlist # note number of events in first run if len(durlist) > 0: N = len(durlist[0]) else: N = 0 if mesg != '': mstr = '(%s) ' % mesg else: mstr = '' print "=== %sstats for StimClass %s ===" % (mstr, self.name) print 'run # min mean max total stdev' print '------ ----- ------- ------- ------- ------- -------' print 'expected %7.3f %7.3f %7.3f %9.2f %s' % \ (tc.min_dur, tc.mean_dur, tc.max_dur, N*tc.mean_dur, tc.dist_type) for rind, durs in enumerate(durlist): mmin, mmean, mmax, mstdev = UTIL.min_mean_max_stdev(durs) ttime = sum(durs) print '%2d %5d %7.3f %7.3f %7.3f %9.2f %7.3f' % \ (rind, len(durs), mmin, mmean, mmax, ttime, mstdev) print if details: digs = gDEF_DEC_PLACES print '-- StimClass %s event durations:' % self.name for rind, durs in enumerate(durlist): dstr = ['%.*f' % (digs, dd) for dd in durs] print ' run %02d: %s' % (rind, ' '.join(dstr)) print print
def show_durlist_stats(self, durlist, mesg='', details=0, sort=0): if mesg != '': mstr = '(%s) ' % mesg else: mstr = '' nevents = len(durlist) total = sum(durlist) print "=== %sstats for TimingClass %s ===" % (mstr, self.name) print " (%d events, total time %g)" % (nevents, total) print ' min mean max stdev' print '------ ------- ------- ------- -------' print 'expected %7.3f %7.3f %7.3f %s' % \ (self.min_dur, self.mean_dur, self.max_dur, self.dist_type) mmin, mmean, mmax, mstdev = UTIL.min_mean_max_stdev(durlist) print 'actual %7.3f %7.3f %7.3f %7.3f\n' % \ (mmin, mmean, mmax, mstdev) if not details: return digs = gDEF_DEC_PLACES if sort: dlist = durlist[:] dlist.sort sstr = ' (sorted)' else: dlist = durlist sstr = '' print '-- TimingClass %s%s event durations:' % (self.name, sstr) dstr = ['%.*f' % (digs, dd) for dd in dlist] print ' %s\n' % ' '.join(dstr)
def set_xlim(self, xlim=[]): if xlim : self.xlim = xlim else: deltax = self.x[1] - self.x[0] xmin, xmean, xmax, xstdev = au.min_mean_max_stdev(self.x) self.xlim = [ xmin - 0.5*deltax, xmax + 0.5*deltax ]
def set_y(self, y): ymin, ymean, ymax, ystdev = au.min_mean_max_stdev(y) self.y = y #self.ymin = np.min(self.y) #self.ymax = np.max(self.y) self.ymin = ymin self.ymax = ymax self.npts = len(y)
def get_TR_offset_stats_str(self, tr, mesg='', wlimit=0.4): """return a string to display statistics regarding within-TR offsets of stimuli tr : show mean/stdev for stimuli within TRs (so 0 <= mean < tr) mesg : display the user message in the output return status, stats string status > 0 : success, warnings were issued = 0 : success, no warnings < 0 : errors """ if not self.ready: return 1, '** M Timing: nothing to compute ISI stats from' if self.nrows != len(self.data): return 1, '** bad MTiming, nrows=%d, datalen=%d, failing...' % \ (self.nrows, len(self.data)) if tr < 0.0: return 1, '** show_TR_offset_stats: invalid TR %s' % tr off_means = [] # ... means per run off_stdev = [] # ... stdevs per run for rind in range(self.nrows): run = self.data[rind] if len(run) == 0: continue # start with list of time remainders (offsets) within each TR roffsets = UTIL.interval_offsets([val for val in run], tr) m0, m1, m2, s = UTIL.min_mean_max_stdev(roffsets) off_means.append(m1) off_stdev.append(s) # if no events ere found, we're outta here if len(off_means) == 0: print 'file %s: no events?' % self.name return 0, '' # and get overall stats (absolute and fractional) offs = self.get_TR_offset_stats(tr) # print out offset info if mesg: mstr = '(%s) ' % mesg else: mstr = '' rstr = '\nwithin-TR stimulus offset statistics %s:\n' % mstr hdr1 = ' overall: ' hdr2 = ' fractional: ' shdr = ' ' rv = 0 if self.nrows > 1: rstr += ' per run\n' \ ' ------------------------------\n' \ ' offset means %s\n' \ ' offset stdevs %s\n' \ '\n' \ % (float_list_string(off_means,ndec=3), float_list_string(off_stdev,ndec=3)) else: hdr1 = ' one run: ' rstr += '%smean = %.3f maxoff = %.3f stdev = %.4f\n' \ % (hdr1, offs[1], offs[2], offs[3]) rstr += '%smean = %.3f maxoff = %.3f stdev = %.4f\n' \ % (hdr2, offs[5], offs[6], offs[7]) # a warning may be issued if the min is positive and the max is small if offs[6] == 0: rstr += '\n%s(stimuli are TR-locked)\n' % shdr elif wlimit > 0.0 and offs[4] > 0 and offs[6] < wlimit: rstr += '\n' \ '%s** WARNING: small maxoff suggests (almost) TR-locked stimuli\n'\ '%s consider: timing_tool.py -round_times (if basis = TENT)\n' \ %(shdr,shdr) rv = 1 # clean up, just to be kind del(off_means); del(off_stdev) return rv, rstr
def show_isi_stats(self, mesg='', run_len=[], tr=0, rest_file=''): """display ISI timing statistics mesg : display the user message first run_len : can be empty, length 1 or length nrows tr : if > 0: show mean/stdev for stimuli within TRs (so 0 <= mean < tr) rest_file : if set, save all rest durations display these statistics: - total time, total stim time, total rest time - total time per run - total stim time per run - total rest time per run - pre-stim rest per run - post-stim response rest per run (if run_len is given) - total ISI rest per run - min/mean/max (stdev) of stim duration - min/mean/max (stdev) of ISI rest """ if not self.ready: print '** M Timing: nothing to compute ISI stats from' return 1 if not (self.mtype & LD.MTYPE_DUR): print '** warning: computing stats without duration' if self.nrows != len(self.data): print '** bad MTiming, nrows=%d, datalen=%d, failing...' % \ (self.nrows, len(self.data)) return 1 # make a sorted copy scopy = self.copy() scopy.sort() # make a copy of format run x stim x [start,end], i.e. is 3-D tdata = scopy.get_start_end_timing() # make an updated run lengths list if len(run_len) == 0: rlens = [0 for rind in range(self.nrows)] elif len(run_len) == 1: rlens = [run_len[0] for rind in range(self.nrows)] elif len(run_len) == self.nrows: rlens = run_len else: # failure print '** invalid len(run_len)=%d, must be one of 0,1,%d' % \ (len(run_len), self.nrows) return 1 if self.verb > 1: print '-- show_isi_stats, run_len = %s, tr = %s, rest_file = %s' \ % (run_len, tr, rest_file) if self.verb > 3: print scopy.make_data_string(nplaces=1, flag_empty=0, check_simple=0, mesg='scopy data') all_stim = [] # all stimulus durations (one row per run) all_isi = [] # all isi times (one row per run) pre_time = [] # pre-stim, per run post_time = [] # pose-stim, per run run_time = [] # total run time, per run errs = 0 # allow a few errors before failing max_errs = 10 for rind in range(self.nrows): run = tdata[rind] rlen = rlens[rind] if len(run) == 0: # empty run all_stim.append([]) all_isi.append([]) pre_time.append(rlen) post_time.append(0.0) run_time.append(rlen) continue # if no run len specified, use end of last stimulus if rlen == 0.0: rlen = run[-1][1] elif rlen < run[-1][1]: print '** run %d: given length = %s, last stim ends at %s' % \ (rind+1, rlen, run[-1][1]) errs += 1 if errs > max_errs: print '** bailing...' return 1 # pre- and post-stim times are set pre = run[0][0] post = rlen - run[-1][1] if pre < 0: print '** ISI error: first stimulus of run %d at negative time %s'%\ (rind+1, run[0][0]) errs += 1 if errs > max_errs: print '** bailing...' return 1 # init accumulation vars stimes = [run[0][1] - run[0][0]] itimes = [] # for each following index, update stim and isi times # (check for bad overlap) for sind in range(1, len(run)): if run[sind][0] < run[sind-1][1]: print '** ISI error: stimuli overlap at run %d, time %s' % \ (rind+1, run[sind][0]) errs += 1 if errs > max_errs: print '** bailing...' return 1 stimes.append(run[sind][1]-run[sind][0]) itimes.append(run[sind][0]-run[sind-1][1]) # store results all_stim.append(stimes) all_isi.append(itimes) pre_time.append(pre) post_time.append(post) run_time.append(rlen) if errs > 0: return 1 # tally the results rtot_stim = [] ; rtot_isi = [] ; rtot_rest = [] stim_list = [] ; isi_list = [] ; nstim_list = [] for rind in range(self.nrows): rtot_stim.append(UTIL.loc_sum(all_stim[rind])) rtot_rest.append(pre_time[rind] + UTIL.loc_sum(all_isi[rind]) + post_time[rind]) rtot_isi.append(UTIL.loc_sum(all_isi[rind])) stim_list.extend(all_stim[rind]) isi_list.extend(all_isi[rind]) nstim_list.append(len(all_stim[rind])) if mesg: mstr = '(%s) ' % mesg else: mstr = '' print '\nISI statistics %s:\n' % mstr print ' total per run' print ' ------ ------------------------------' print ' total time %6.1f %s' % \ (UTIL.loc_sum(run_time), float_list_string(run_time, ndec=1)) print ' total time: stim %6.1f %s' % \ (UTIL.loc_sum(rtot_stim),float_list_string(rtot_stim,7,ndec=1)) print ' total time: rest %6.1f %s' % \ (UTIL.loc_sum(rtot_rest),float_list_string(rtot_rest,7,ndec=1)) print '' print ' rest: total isi %6.1f %s' % \ (UTIL.loc_sum(rtot_isi), float_list_string(rtot_isi,7,ndec=1)) print ' rest: pre stim %6.1f %s' % \ (UTIL.loc_sum(pre_time), float_list_string(pre_time,7,ndec=1)) print ' rest: post stim %6.1f %s' % \ (UTIL.loc_sum(post_time),float_list_string(post_time,7,ndec=1)) print '' print ' num stimuli %6d %s' % \ (UTIL.loc_sum(nstim_list), float_list_string(nstim_list,7,ndec=0)) print '\n' print ' min mean max stdev' print ' ------- ------- ------- -------' print ' rest: pre-stim %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(pre_time)) print ' rest: post-stim %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(post_time)) print '' for ind in range(self.nrows): m0, m1, m2, s = UTIL.min_mean_max_stdev(all_isi[ind]) print ' rest: run #%d ISI %7.3f %7.3f %7.3f %7.3f' % \ (ind, m0, m1, m2, s) print '' print ' all runs: ISI %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(isi_list)) print ' all runs: stimuli %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(stim_list)) print '' # and possibly print out offset info if tr > 0: self.show_TR_offset_stats(tr, '') # maybe write all rest durations if rest_file: all_rest = copy.deepcopy(all_isi) for run, rest in enumerate(all_rest): rest[:0] = [pre_time[run]] rest.append(post_time[run]) UTIL.write_to_timing_file(all_rest, rest_file) # clean up, just to be kind del(all_stim); del(all_isi); del(pre_time); del(post_time); del(run_time) del(rtot_stim); del(rtot_isi); del(rtot_rest); del(stim_list) del(isi_list); del(nstim_list) del(scopy) del(tdata)
def get_TR_offset_stats_str(self, tr, mesg='', wlimit=0.4): """return a string to display statistics regarding within-TR offsets of stimuli tr : show mean/stdev for stimuli within TRs (so 0 <= mean < tr) mesg : display the user message in the output return status, stats string status > 0 : success, warnings were issued = 0 : success, no warnings < 0 : errors """ if not self.ready: return 1, '** M Timing: nothing to compute ISI stats from' if self.nrows != len(self.data): return 1, '** bad MTiming, nrows=%d, datalen=%d, failing...' % \ (self.nrows, len(self.data)) if tr < 0.0: return 1, '** show_TR_offset_stats: invalid TR %s' % tr off_means = [] # ... means per run off_stdev = [] # ... stdevs per run for rind in range(self.nrows): run = self.data[rind] if len(run) == 0: continue # start with list of time remainders (offsets) within each TR roffsets = UTIL.interval_offsets([val for val in run], tr) m0, m1, m2, s = UTIL.min_mean_max_stdev(roffsets) off_means.append(m1) off_stdev.append(s) # if no events ere found, we're outta here if len(off_means) == 0: print 'file %s: no events?' % self.name return 0, '' # and get overall stats (absolute and fractional) offs = self.get_TR_offset_stats(tr) # print out offset info if mesg: mstr = '(%s) ' % mesg else: mstr = '' rstr = '\nwithin-TR stimulus offset statistics %s:\n' % mstr hdr1 = ' overall: ' hdr2 = ' fractional: ' shdr = ' ' rv = 0 if self.nrows > 1: rstr += ' per run\n' \ ' ------------------------------\n' \ ' offset means %s\n' \ ' offset stdevs %s\n' \ '\n' \ % (float_list_string(off_means,ndec=3), float_list_string(off_stdev,ndec=3)) else: hdr1 = ' one run: ' rstr += '%smean = %.3f maxoff = %.3f stdev = %.4f\n' \ % (hdr1, offs[1], offs[2], offs[3]) rstr += '%smean = %.3f maxoff = %.3f stdev = %.4f\n' \ % (hdr2, offs[5], offs[6], offs[7]) # a warning may be issued if the min is positive and the max is small if offs[6] == 0: rstr += '\n%s(stimuli are TR-locked)\n' % shdr elif wlimit > 0.0 and offs[4] > 0 and offs[6] < wlimit: rstr += '\n' \ '%s** WARNING: small maxoff suggests (almost) TR-locked stimuli\n'\ '%s consider: timing_tool.py -round_times (if basis = TENT)\n' \ %(shdr,shdr) rv = 1 # clean up, just to be kind del (off_means) del (off_stdev) return rv, rstr
def show_isi_stats(self, mesg='', run_len=[], tr=0, rest_file=''): """display ISI timing statistics mesg : display the user message first run_len : can be empty, length 1 or length nrows tr : if > 0: show mean/stdev for stimuli within TRs (so 0 <= mean < tr) rest_file : if set, save all rest durations display these statistics: - total time, total stim time, total rest time - total time per run - total stim time per run - total rest time per run - pre-stim rest per run - post-stim response rest per run (if run_len is given) - total ISI rest per run - min/mean/max (stdev) of stim duration - min/mean/max (stdev) of ISI rest """ if not self.ready: print '** M Timing: nothing to compute ISI stats from' return 1 if not (self.mtype & LD.MTYPE_DUR): print '** warning: computing stats without duration' if self.nrows != len(self.data): print '** bad MTiming, nrows=%d, datalen=%d, failing...' % \ (self.nrows, len(self.data)) return 1 # make a sorted copy scopy = self.copy() scopy.sort() # make a copy of format run x stim x [start,end], i.e. is 3-D tdata = scopy.get_start_end_timing() # make an updated run lengths list if len(run_len) == 0: rlens = [0 for rind in range(self.nrows)] elif len(run_len) == 1: rlens = [run_len[0] for rind in range(self.nrows)] elif len(run_len) == self.nrows: rlens = run_len else: # failure print '** invalid len(run_len)=%d, must be one of 0,1,%d' % \ (len(run_len), self.nrows) return 1 if self.verb > 1: print '-- show_isi_stats, run_len = %s, tr = %s, rest_file = %s' \ % (run_len, tr, rest_file) if self.verb > 3: print scopy.make_data_string(nplaces=1, flag_empty=0, check_simple=0, mesg='scopy data') all_stim = [] # all stimulus durations (one row per run) all_isi = [] # all isi times (one row per run) pre_time = [] # pre-stim, per run post_time = [] # pose-stim, per run run_time = [] # total run time, per run errs = 0 # allow a few errors before failing max_errs = 10 for rind in range(self.nrows): run = tdata[rind] rlen = rlens[rind] if len(run) == 0: # empty run all_stim.append([]) all_isi.append([]) pre_time.append(rlen) post_time.append(0.0) run_time.append(rlen) continue # if no run len specified, use end of last stimulus if rlen == 0.0: rlen = run[-1][1] elif rlen < run[-1][1]: print '** run %d: given length = %s, last stim ends at %s' % \ (rind+1, rlen, run[-1][1]) errs += 1 if errs > max_errs: print '** bailing...' return 1 # pre- and post-stim times are set pre = run[0][0] post = rlen - run[-1][1] if pre < 0: print '** ISI error: first stimulus of run %d at negative time %s'%\ (rind+1, run[0][0]) errs += 1 if errs > max_errs: print '** bailing...' return 1 # init accumulation vars stimes = [run[0][1] - run[0][0]] itimes = [] # for each following index, update stim and isi times # (check for bad overlap) for sind in range(1, len(run)): if run[sind][0] < run[sind - 1][1]: print '** ISI error: stimuli overlap at run %d, time %s' % \ (rind+1, run[sind][0]) errs += 1 if errs > max_errs: print '** bailing...' return 1 stimes.append(run[sind][1] - run[sind][0]) itimes.append(run[sind][0] - run[sind - 1][1]) # store results all_stim.append(stimes) all_isi.append(itimes) pre_time.append(pre) post_time.append(post) run_time.append(rlen) if errs > 0: return 1 # tally the results rtot_stim = [] rtot_isi = [] rtot_rest = [] stim_list = [] isi_list = [] nstim_list = [] for rind in range(self.nrows): rtot_stim.append(UTIL.loc_sum(all_stim[rind])) rtot_rest.append(pre_time[rind] + UTIL.loc_sum(all_isi[rind]) + post_time[rind]) rtot_isi.append(UTIL.loc_sum(all_isi[rind])) stim_list.extend(all_stim[rind]) isi_list.extend(all_isi[rind]) nstim_list.append(len(all_stim[rind])) if mesg: mstr = '(%s) ' % mesg else: mstr = '' print '\nISI statistics %s:\n' % mstr print ' total per run' print ' ------ ------------------------------' print ' total time %6.1f %s' % \ (UTIL.loc_sum(run_time), float_list_string(run_time, ndec=1)) print ' total time: stim %6.1f %s' % \ (UTIL.loc_sum(rtot_stim),float_list_string(rtot_stim,7,ndec=1)) print ' total time: rest %6.1f %s' % \ (UTIL.loc_sum(rtot_rest),float_list_string(rtot_rest,7,ndec=1)) print '' print ' rest: total isi %6.1f %s' % \ (UTIL.loc_sum(rtot_isi), float_list_string(rtot_isi,7,ndec=1)) print ' rest: pre stim %6.1f %s' % \ (UTIL.loc_sum(pre_time), float_list_string(pre_time,7,ndec=1)) print ' rest: post stim %6.1f %s' % \ (UTIL.loc_sum(post_time),float_list_string(post_time,7,ndec=1)) print '' print ' num stimuli %6d %s' % \ (UTIL.loc_sum(nstim_list), float_list_string(nstim_list,7,ndec=0)) print '\n' print ' min mean max stdev' print ' ------- ------- ------- -------' print ' rest: pre-stim %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(pre_time)) print ' rest: post-stim %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(post_time)) print '' for ind in range(self.nrows): m0, m1, m2, s = UTIL.min_mean_max_stdev(all_isi[ind]) print ' rest: run #%d ISI %7.3f %7.3f %7.3f %7.3f' % \ (ind, m0, m1, m2, s) print '' print ' all runs: ISI %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(isi_list)) print ' all runs: stimuli %7.3f %7.3f %7.3f %7.3f' % \ (UTIL.min_mean_max_stdev(stim_list)) print '' # and possibly print out offset info if tr > 0: self.show_TR_offset_stats(tr, '') # maybe write all rest durations if rest_file: all_rest = copy.deepcopy(all_isi) for run, rest in enumerate(all_rest): rest[:0] = [pre_time[run]] rest.append(post_time[run]) UTIL.write_to_timing_file(all_rest, rest_file) # clean up, just to be kind del (all_stim) del (all_isi) del (pre_time) del (post_time) del (run_time) del (rtot_stim) del (rtot_isi) del (rtot_rest) del (stim_list) del (isi_list) del (nstim_list) del (scopy) del (tdata)