Exemple #1
0
    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]
Exemple #2
0
   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]
Exemple #3
0
    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
Exemple #4
0
    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)
Exemple #5
0
 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 ]
Exemple #6
0
 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)
Exemple #7
0
   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
Exemple #8
0
   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)
Exemple #9
0
    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
Exemple #10
0
    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)