Example #1
0
    def start(self, block=True, evt=None, duration=None, message=None):
        if self.end_evt:
            self.end_evt.set()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if duration:
            # self.duration = 1
            self.duration = duration
            self.reset()

        if message:
            self.message = message

        self.timer = Timer(1000, self._update_time, delay=1000)
        self._continued = False

        if block:
            self.join(evt=evt)
            if evt == self.end_evt:
                self.end_evt = None
Example #2
0
    def start_timer(self):
        st = time.time()
        self._start_time = st
        def update_time():
            e = round(time.time() - st)
            self.trait_set(_elapsed=e)

        self._timer = Timer(1000, update_time)
        self._timer.start()
Example #3
0
    def start_scan(self, period=None):
        """

        :param period: delapy between triggers in milliseconds
        :return:
        """
        if self.timer is not None:
            self.timer.Stop()
            self.timer.wait_for_completion()

        self._scanning = True
        self.info('Starting scan')

        d = self.scan_width * 60 #* 1000/self.scan_period
        # print self.scan_width, self.scan_period
        if self.graph_scan_data:
            self.info('Graph recording enabled')
            self.graph.set_scan_width(d)

        if self.record_scan_data:
            self.info('Recording scan enabled')
            if self.dm_kind == 'h5':
                from pychron.managers.data_managers.h5_data_manager import H5DataManager

                klass = H5DataManager
            else:
                klass = CSVDataManager

            dm = self.data_manager
            if dm is None:
                self.data_manager = dm = klass()

            dm.delimiter = '\t'

            dw = DataWarehouse(root=paths.device_scan_dir)
            dw.build_warehouse()

            dm.new_frame(base_frame_name=self.name, directory=dw.get_current_dir())
            self.scan_path = dm.get_current_path()

            if self.dm_kind == 'h5':
                g = dm.new_group('scans')
                dm.new_table(g, 'scan1')

            if self.auto_start:
                self.save_scan_to_db()

        if period is None:
            period = self.scan_period * self.time_dict[self.scan_units]

        from pychron.core.helpers.timer import Timer
        self.timer = Timer(period, self.scan)
        self.info('Scan started {} period={}'.format(self.scan_func, period))
Example #4
0
    def start_timer(self):
        st = time.time()
        self._post = datetime.now()

        def update_time():
            e = round(time.time() - st)
            d = {'_elapsed': e}
            if self._run_start:
                re = round(time.time() - self._run_start)
                d['_run_elapsed'] = re
            self.trait_set(**d)

        self._timer = Timer(1000, update_time)
Example #5
0
    def timer_factory(self, func=None, period=150):
        """

            reuse timer if func is the same

        """

        timer = self.timer
        if func is None:
            func = self._inprogress_update

        if timer is None:
            self._not_moving_count = 0
            timer = Timer(period, func, delay=250)
        elif timer.func == func:
            if timer.isActive():
                self.debug('reusing old timer')
            else:
                self._not_moving_count = 0
                timer = Timer(period, func, delay=250)
        else:
            timer.stop()
            self._not_moving_count = 0
            time.sleep(period / 1000.)
            timer = Timer(period, func)

        timer.set_interval(period)
        return timer
Example #6
0
    def start(self, block=True, evt=None, duration=None, message=None):
        if self.end_evt:
            self.end_evt.set()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if duration:
            # self.duration = 1
            self.duration = duration
            self.reset()

        if message:
            self.message = message

        self.timer = Timer(1000, self._update_time, delay=1000)
        self._continued = False

        if block:
            self.join(evt=evt)
            if evt == self.end_evt:
                self.end_evt = None
Example #7
0
    def opened(self, ui):
        self.edit_traits(view='display_view',
                         #                  parent=self.ui.control
                         )

        t = Timer(3000, self._check_connection)
        self._timer = t
Example #8
0
    def timer_factory(self):
        """
            reuse timer if possible
        """
        timer = self.timer

        func = self._update_position
        if timer is None:
            self._not_moving_count = 0
            timer = Timer(250, func)
        else:
            if timer.isActive():
                self.debug('reusing old timer')
            else:
                self._not_moving_count = 0
                timer = Timer(250, func)

        return timer
Example #9
0
    def timer_factory(self):
        """
            reuse timer if possible
        """
        timer = self.timer

        func = self._update_position
        if timer is None:
            self._not_moving_count = 0
            timer = Timer(250, func)
        else:
            if timer.isActive():
                self.debug('reusing old timer')
            else:
                self._not_moving_count = 0
                timer = Timer(250, func)

        return timer
Example #10
0
    def _timer_factory(self, func=None):

        if func is None:
            func = self._update_scan_graph

        if self.timer:
            self.timer.Stop()
            self.timer.wait_for_completion()

        mult = 1000
        return Timer(self.update_period * mult, func)
Example #11
0
    def start(self, block=True, evt=None, wtime=None):
        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if wtime:
            self.wtime = wtime
            self.reset()

        self.timer = Timer(1000, self._update_time, delay=1000)
        self._continued = False

        if block:
            self.join()
Example #12
0
    def start_timer(self):
        st = time.time()
        self._post = datetime.now()

        def update_time():
            e = round(time.time() - st)
            d = {"_elapsed": e}
            if self._run_start:
                re = round(time.time() - self._run_start)
                d["_run_elapsed"] = re
            self.trait_set(**d)

        self._timer = Timer(1000, update_time)
        self._timer.start()
Example #13
0
    def _execute(self):

        yd = self._read_control_path()

        if yd is None:
            sp = 1000
        else:
            sp = yd['period']

        # starts automatically
        self.debug('scan starting')
        self._timer = Timer(sp, self._scan)

        self.info('scan started')

        #            yd = self._read_control_path()
        if yd is not None:
            # start a control thread
            self._control_thread = Thread(target=self._control, args=(yd, ))
            self._control_thread.start()
            self.info('control started')
Example #14
0
    def start(self, block=True, evt=None, wtime=None):
        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if wtime:
            self.wtime=wtime
            self.reset()

        self.timer = Timer(1000, self._update_time,
                           delay=1000
                           )
        self._continued = False

        if block:
            self.join()
Example #15
0
    def timer_factory(self, func=None, period=150):
        """

            reuse timer if func is the same

        """

        timer = self.timer
        if func is None:
            func = self._inprogress_update

        if timer is None:
            self._not_moving_count = 0
            timer = Timer(period, func, delay=250)
        elif timer.func == func:
            if timer.isActive():
                self.debug('reusing old timer')
            else:
                self._not_moving_count = 0
                timer = Timer(period, func, delay=250)
        else:
            timer.stop()
            self._not_moving_count = 0
            time.sleep(period / 1000.)
            timer = Timer(period, func)

        timer.set_interval(period)
        return timer
Example #16
0
class WaitControl(Loggable):
    page_name = Str('Wait')
    message = Str
    message_color = Color('black')

    high = Float
    wtime = Float(10)
    low_name = Float(1)

    current_time = Float
    #     current_time = Property(depends_on='current_time')

    auto_start = Bool(False)
    timer = None
    end_evt = None

    continue_button = Button('Continue')

    _continued = Bool
    _canceled = Bool

    def __init__(self, *args, **kw):
        self.reset()
        super(WaitControl, self).__init__(*args, **kw)
        if self.auto_start:
            self.start(evt=self.end_evt)

    def is_active(self):
        if self.timer:
            return self.timer.isActive()

    def is_canceled(self):
        return self._canceled

    def is_continued(self):
        return self._continued

    def join(self):
        time.sleep(0.25)
        while not self.end_evt.is_set():
            time.sleep(0.05)
        self.debug('Join finished')

    def start(self, block=True, evt=None, wtime=None):
        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if wtime:
            self.wtime = wtime
            self.reset()

        self.timer = Timer(1000, self._update_time, delay=1000)
        self._continued = False

        if block:
            self.join()

    def stop(self):
        self._end()
        self.debug('wait dialog stopped')
        if self.current_time > 1:
            self.message = 'Stopped'
            self.message_color = 'red'
        self.current_time = 0

    def reset(self):
        self.high = self.wtime
        self.current_time = self.wtime
#===============================================================================
# private
#===============================================================================

    def _continue(self):
        self._continued = True
        self._end()
        self.current_time = 0

    def _end(self):
        self.message = ''

        if self.timer is not None:
            self.timer.Stop()
        if self.end_evt is not None:
            self.end_evt.set()

    def _update_time(self):
        if self.timer and self.timer.isActive():
            self.current_time -= 1

    def _current_time_changed(self):
        if self.current_time <= 0:
            self._end()
            self._canceled = False
#===============================================================================
# handlers
#===============================================================================

    def _continue_button_fired(self):
        self._continue()

    def _high_changed(self, v):
        self.wtime = v
        self.current_time = v

    def traits_view(self):
        v = View(
            VGroup(
                CustomLabel('message',
                            size=14,
                            weight='bold',
                            color_name='message_color'),
                HGroup(Spring(width=-5, springy=False),
                       Item('high', label='Set Max. Seconds'), spring,
                       UItem('continue_button')),
                HGroup(
                    Spring(width=-5, springy=False),
                    Item('current_time',
                         show_label=False,
                         editor=RangeEditor(
                             mode='slider',
                             low_name='low_name',
                             high_name='wtime',
                         ))),
            ), )
        return v
Example #17
0
class WaitControl(Loggable):
    page_name = Str('Wait')
    message = Str
    message_color = Color('black')

    high = Int
    duration = Float(10)

    current_time = Float
    current_display_time = Property(depends_on='current_time')

    auto_start = Bool(False)
    timer = None
    end_evt = None

    continue_button = Button('Continue')
    pause_button = Button('Pause')
    _paused = Bool
    _continued = Bool
    _canceled = Bool
    _no_update = False

    def __init__(self, *args, **kw):
        self.reset()
        super(WaitControl, self).__init__(*args, **kw)
        if self.auto_start:
            self.start(evt=self.end_evt)

    def is_active(self):
        if self.timer:
            return self.timer.isActive()

    def is_canceled(self):
        return self._canceled

    def is_continued(self):
        return self._continued

    def join(self, evt=None):
        if evt is None:
            evt = self.end_evt

        if self.duration > 1:
            evt.wait(self.duration - 1)

        while not evt.wait(timeout=0.25):
            time.sleep(0.25)

        self.debug('Join finished')

    def start(self, block=True, evt=None, duration=None, message=None):
        if self.end_evt:
            self.end_evt.set()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if duration:
            # self.duration = 1
            self.duration = duration
            self.reset()

        if message:
            self.message = message

        self.timer = Timer(1000, self._update_time, delay=1000)
        self._continued = False

        if block:
            self.join(evt=evt)
            if evt == self.end_evt:
                self.end_evt = None

    def stop(self):
        self._end()
        self.debug('wait dialog stopped')
        if self.current_time > 1:
            self.message = 'Stopped'
            self.message_color = 'red'
            # self.current_time = 0

    def reset(self):
        with no_update(self, fire_update_needed=False):
            self.high = int(self.duration)
            self.current_time = self.duration
            self._paused = False

    # ===============================================================================
    # private
    # ===============================================================================

    def _continue(self):
        self._paused = False
        self._continued = True
        self._end()
        self.current_time = 0

    def _end(self):
        self.message = ''

        if self.timer is not None:
            self.timer.Stop()
        if self.end_evt is not None:
            self.end_evt.set()

    def _update_time(self):
        if self._paused:
            return

        ct = self.current_time
        if self.timer and self.timer.isActive():
            self.current_time -= 1
            ct -= 1
            # self.debug('Current Time={}/{}'.format(ct, self.duration))
            if ct <= 0:
                self._end()
                self._canceled = False
            else:
                self.current_time = ct

                # def _current_time_changed(self):
                # if self.current_time <= 0:
                # self._end()
                # self._canceled = False

    def _get_current_display_time(self):
        return '{:03d}'.format(int(self.current_time))

    # ===============================================================================
    # handlers
    # ===============================================================================
    def _pause_button_fired(self):
        self._paused = not self._paused

    def _continue_button_fired(self):
        self._continue()

    def _high_changed(self, v):
        if self._no_update:
            return

        self.duration = v
        self.current_time = v
Example #18
0
class WaitControl(Loggable):
    page_name = Str('Wait')
    message = Str
    message_color = Color('black')

    high = Float
    wtime = Float(10)
    low_name = Float(1)

    current_time = Float
#     current_time = Property(depends_on='current_time')

    auto_start = Bool(False)
    timer = None
    end_evt = None

    continue_button = Button('Continue')

    _continued = Bool
    _canceled = Bool

    def __init__(self, *args, **kw):
        self.reset()
        super(WaitControl, self).__init__(*args, **kw)
        if self.auto_start:
            self.start(evt=self.end_evt)

    def is_active(self):
        if self.timer:
            return self.timer.isActive()

    def is_canceled(self):
        return self._canceled

    def is_continued(self):
        return self._continued

    def join(self):
        time.sleep(0.25)
        while not self.end_evt.is_set():
            time.sleep(0.05)
        self.debug('Join finished')

    def start(self, block=True, evt=None, wtime=None):
        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if wtime:
            self.wtime=wtime
            self.reset()

        self.timer = Timer(1000, self._update_time,
                           delay=1000
                           )
        self._continued = False

        if block:
            self.join()

    def stop(self):
        self._end()
        self.debug('wait dialog stopped')
        if self.current_time > 1:
            self.message = 'Stopped'
            self.message_color = 'red'
        self.current_time = 0

    def reset(self):
        self.high = self.wtime
        self.current_time = self.wtime
#===============================================================================
# private
#===============================================================================

    def _continue(self):
        self._continued = True
        self._end()
        self.current_time = 0

    def _end(self):
        self.message = ''

        if self.timer is not None:
            self.timer.Stop()
        if self.end_evt is not None:
            self.end_evt.set()

    def _update_time(self):
        if self.timer and self.timer.isActive():
            self.current_time -= 1

    def _current_time_changed(self):
        if self.current_time <= 0:
            self._end()
            self._canceled = False
#===============================================================================
# handlers
#===============================================================================
    def _continue_button_fired(self):
        self._continue()

    def _high_changed(self, v):
        self.wtime = v
        self.current_time = v

    def traits_view(self):
        v = View(VGroup(
                        CustomLabel('message',
                                    size=14,
                                    weight='bold',
                                    color_name='message_color'
                                    ),
                        HGroup(
                               Spring(width=-5, springy=False),
                               Item('high', label='Set Max. Seconds'),
                               spring, UItem('continue_button')
                               ),
                        HGroup(
                               Spring(width=-5, springy=False),
                               Item('current_time', show_label=False,
                                    editor=RangeEditor(mode='slider',
                                                           low_name='low_name',
                                                           high_name='wtime',
                                                           ))
                               ),
                        ),
               )
        return v
Example #19
0
class ScanableDevice(ViewableDevice):
    scan_button = Event
    scan_label = Property(depends_on='_scanning')
    _scanning = Bool(False)

    alarms = List(Alarm)

    is_scanable = Bool(False)
    scan_func = Any
    scan_lock = None
    timer = None
    scan_period = Float(1000, enter_set=True, auto_set=False)
    scan_width = Float(5, enter_set=True, auto_set=False)
    scan_units = 'ms'
    record_scan_data = Bool(False)
    graph_scan_data = Bool(False)
    scan_path = Str
    auto_start = Bool(False)
    scan_root = Str
    scan_name = Str

    graph = Instance('pychron.graph.graph.Graph')
    graph_ytitle = Str

    data_manager = None
    time_dict = dict(ms=1, s=1000, m=60.0 * 1000, h=60.0 * 60.0 * 1000)

    dm_kind = 'csv'
    use_db = False
    _auto_started = False

    def is_scanning(self):
        return self._scanning

    def _scan_path_changed(self):
        self.scan_root = os.path.split(self.scan_path)[0]
        self.scan_name = os.path.basename(self.scan_path)

    # ===============================================================================
    # streamin interface
    # ===============================================================================
    def setup_scan(self):
        # should get scan settings from the config file not the initialization.xml
        config = self.get_configuration()
        if config.has_section('Scan'):
            enabled = self.config_get(config, 'Scan', 'enabled', cast='boolean', optional=True, default=True)
            self.is_scanable = enabled
            if enabled:
                self.set_attribute(config, 'auto_start', 'Scan', 'auto_start', cast='boolean', default=False)
                self.set_attribute(config, 'scan_period', 'Scan', 'period', cast='float')
                self.set_attribute(config, 'scan_width', 'Scan', 'width', cast='float')
                self.set_attribute(config, 'scan_units', 'Scan', 'units')
                self.set_attribute(config, 'record_scan_data', 'Scan', 'record', cast='boolean')
                self.set_attribute(config, 'graph_scan_data', 'Scan', 'graph', cast='boolean')
                # self.set_attribute(config, 'use_db', 'DataManager', 'use_db', cast='boolean', default=False)
                # self.set_attribute(config, 'dm_kind', 'DataManager', 'kind', default='csv')

    def setup_alarms(self):
        config = self.get_configuration()
        if config.has_section('Alarms'):
            for opt in config.options('Alarms'):
                self.alarms.append(Alarm(
                    name=opt,
                    alarm_str=config.get('Alarms', opt)))

    def _scan_hook(self, *args, **kw):
        pass

    def _scan_(self, *args):
        if self.scan_func:

            try:
                v = getattr(self, self.scan_func)(verbose=False)
            except AttributeError as e:
                print('exception', e)
                return

            if v is not None:
                # self.debug('current scan value={}'.format(v))
                self.current_scan_value = str(v)

                # self.debug('current scan func={}, value ={}'.format(self.scan_func, v))

                x = None
                if self.graph_scan_data:
                    self.debug('graphing scan data')
                    if isinstance(v, tuple):
                        x = self.graph.record_multiple(v)
                    elif isinstance(v, PlotRecord):
                        for pi, d in zip(v.plotids, v.data):

                            if isinstance(d, tuple):
                                x = self.graph.record_multiple(d, plotid=pi)
                            else:
                                x = self.graph.record(d, plotid=pi)
                        v = v.as_data_tuple()

                    else:
                        x = self.graph.record(v)
                        v = (v,)
                if self.record_scan_data:
                    self.debug('recording scan data')
                    if x is None:
                        x = time.time()

                    if self.dm_kind == 'csv':
                        ts = generate_datetimestamp()

                        self.data_manager.write_to_frame((ts, '{:<8s}'.format('{:0.2f}'.format(x))) + v)
                    else:
                        tab = self.data_manager.get_table('scan1', '/scans')
                        if tab is not None:
                            r = tab.row
                            r['time'] = x
                            r['value'] = v[0]
                            r.append()
                            tab.flush()

                self._scan_hook(v)

            else:
                '''
                    scan func must return a value or we will stop the scan
                    since the timer runs on the main thread any long comms timeouts
                    slow user interaction
                '''
                if self._no_response_counter > 3:
                    self.timer.Stop()
                    self.info('no response. stopping scan func={}'.format(self.scan_func))
                    self._scanning = False
                    self._no_response_counter = 0

                else:
                    self._no_response_counter += 1

    def scan(self, *args, **kw):
        if self.scan_lock is None:
            self.scan_lock = Lock()

        with self.scan_lock:
            self._scan_(*args, **kw)

    def start_scan(self, period=None):
        """

        :param period: delapy between triggers in milliseconds
        :return:
        """
        if self.timer is not None:
            self.timer.Stop()
            self.timer.wait_for_completion()

        self._scanning = True
        self.info('Starting scan')

        d = self.scan_width * 60 #* 1000/self.scan_period
        # print self.scan_width, self.scan_period
        if self.graph_scan_data:
            self.info('Graph recording enabled')
            self.graph.set_scan_width(d)

        if self.record_scan_data:
            self.info('Recording scan enabled')
            if self.dm_kind == 'h5':
                from pychron.managers.data_managers.h5_data_manager import H5DataManager

                klass = H5DataManager
            else:
                klass = CSVDataManager

            dm = self.data_manager
            if dm is None:
                self.data_manager = dm = klass()

            dm.delimiter = '\t'

            dw = DataWarehouse(root=paths.device_scan_dir)
            dw.build_warehouse()

            dm.new_frame(base_frame_name=self.name, directory=dw.get_current_dir())
            self.scan_path = dm.get_current_path()

            if self.dm_kind == 'h5':
                g = dm.new_group('scans')
                dm.new_table(g, 'scan1')

            if self.auto_start:
                self.save_scan_to_db()

        if period is None:
            period = self.scan_period * self.time_dict[self.scan_units]

        from pychron.core.helpers.timer import Timer
        self.timer = Timer(period, self.scan)
        self.info('Scan started {} period={}'.format(self.scan_func, period))

    def save_scan_to_db(self):
        from pychron.database.adapters.device_scan_adapter import DeviceScanAdapter

        db = DeviceScanAdapter(name=paths.device_scan_db,
                               kind='sqlite')
        db.connect()
        dev = db.add_device(self.name, klass=self.__class__.__name__)
        s = db.add_scan(dev)

        path = self.scan_path
        db.add_path(s, path)
        self.info('saving scan {} to database {}'.format(path, paths.device_scan_db))

        db.commit()

    def stop_scan(self):
        self.info('Stoppiing scan')

        self._scanning = False
        if self.timer is not None:
            self.timer.Stop()

        if self.record_scan_data and not self._auto_started:
            if self.use_db:
                if self.confirmation_dialog('Save to Database'):
                    self.save_scan_to_db()
                else:
                    if self.data_manager:
                        self.data_manager.delete_frame()

        if self.data_manager:
            self.data_manager.close_file()
        self._auto_started = False
        self.info('Scan stopped')

    def _get_scan_label(self):
        return 'Start' if not self._scanning else 'Stop'

    def _scan_button_fired(self):
        self.debug('scan button fired. scanning {}'.format(self._scanning))
        if self._scanning:
            self.stop_scan()
        else:
            self.start_scan()

    def _scan_period_changed(self):
        if self._scanning:
            self.stop_scan()
            self.start_scan()

    def _graph_default(self):
        from pychron.graph.time_series_graph import TimeSeriesStreamGraph

        g = TimeSeriesStreamGraph()
        self.graph_builder(g)

        return g

    def graph_builder(self, g, **kw):
        g.new_plot(padding=[50, 5, 5, 35],
                   zoom=True,
                   pan=True,
                   **kw)

        g.set_y_title(self.graph_ytitle)
        g.set_x_title('Time')
        g.new_series()

    def current_state_view(self):
        g = VGroup(Item('graph', show_label=False, style='custom'),
                   VGroup(Item('scan_func', label='Function', style='readonly'),

                          HGroup(Item('scan_period', label='Period ({})'.format(self.scan_units)), spring),
                          Item('current_scan_value', style='readonly')),
                   VGroup(
                       HGroup(Item('scan_button', editor=ButtonEditor(label_value='scan_label'),
                                   show_label=False),
                              spring),
                       Item('scan_root',
                            style='readonly',
                            label='Scan directory',
                            visible_when='object.record_scan_data'),
                       Item('scan_name', label='Scan name',
                            style='readonly',
                            visible_when='object.record_scan_data'),
                       visible_when='object.is_scanable'),

                   label='Scan')
        v = super(ScanableDevice, self).current_state_view()
        v.content.content.append(g)
        return v
Example #20
0
class WaitControl(Loggable):
    page_name = Str('Wait')
    message = Str
    message_color = Color('black')

    high = Float
    duration = Float(10)

    current_time = Float

    auto_start = Bool(False)
    timer = None
    end_evt = None

    continue_button = Button('Continue')
    pause_button = Button('Pause')
    _paused = Bool
    _continued = Bool
    _canceled = Bool
    _no_update = False

    def __init__(self, *args, **kw):
        self.reset()
        super(WaitControl, self).__init__(*args, **kw)
        if self.auto_start:
            self.start(evt=self.end_evt)

    def is_active(self):
        if self.timer:
            return self.timer.isActive()

    def is_canceled(self):
        return self._canceled

    def is_continued(self):
        return self._continued

    def join(self, evt=None):
        if evt is None:
            evt = self.end_evt

        # time.sleep(0.25)

        evt.wait(0.25)

        # while not self.end_evt.is_set():
        while not evt.wait(timeout=0.1):
            pass
        # while not evt.is_set():
        #     # time.sleep(0.005)
        #     evt.wait(0.005)

        self.debug('Join finished')

    def start(self, block=True, evt=None, duration=None, message=None):
        if self.end_evt:
            self.end_evt.set()

        if evt is None:
            evt = Event()

        if evt:
            evt.clear()
            self.end_evt = evt

        if self.timer:
            self.timer.stop()
            self.timer.wait_for_completion()

        if duration:
            # self.duration = 1
            self.duration = duration
            self.reset()

        if message:
            self.message = message

        self.timer = Timer(1000, self._update_time, delay=1000)
        self._continued = False

        if block:
            self.join(evt=evt)
            if evt == self.end_evt:
                self.end_evt = None

    def stop(self):
        self._end()
        self.debug('wait dialog stopped')
        if self.current_time > 1:
            self.message = 'Stopped'
            self.message_color = 'red'
            # self.current_time = 0

    def reset(self):
        with no_update(self, fire_update_needed=False):
            self.high = self.duration
            self.current_time = self.duration
            self._paused = False

    # ===============================================================================
    # private
    # ===============================================================================

    def _continue(self):
        self._paused = False
        self._continued = True
        self._end()
        self.current_time = 0

    def _end(self):
        self.message = ''

        if self.timer is not None:
            self.timer.Stop()
        if self.end_evt is not None:
            self.end_evt.set()

    def _update_time(self):
        if self._paused:
            return

        ct = self.current_time
        if self.timer and self.timer.isActive():
            self.current_time -= 1
            ct -= 1
            # self.debug('Current Time={}/{}'.format(ct, self.duration))
            if ct <= 0:
                self._end()
                self._canceled = False
            else:
                self.current_time = ct

                # def _current_time_changed(self):
                # if self.current_time <= 0:
                # self._end()
                # self._canceled = False

    # ===============================================================================
    # handlers
    # ===============================================================================
    def _pause_button_fired(self):
        self._paused = not self._paused

    def _continue_button_fired(self):
        self._continue()

    def _high_changed(self, v):
        if self._no_update:
            return

        self.duration = v
        self.current_time = v
Example #21
0
class ExperimentStats(Loggable):
    elapsed = Property(depends_on="_elapsed")
    _elapsed = Float

    run_elapsed = Property(depends_on="_run_elapsed")
    _run_elapsed = Float

    nruns = Int
    nruns_finished = Int
    etf = String
    start_at = String
    end_at = String
    run_duration = String
    current_run_duration = String
    total_time = Property(depends_on="_total_time")
    _total_time = Float

    _timer = Any

    delay_between_analyses = Float
    delay_before_analyses = Float
    # _start_time = None
    _post = None

    use_clock = Bool(False)
    clock = Instance(PieClockModel, ())
    duration_tracker = Instance(AutomatedRunDurationTracker, ())
    _run_start = 0
    # experiment_queue = Any

    def calculate_duration(self, runs=None):
        #        if runs is None:
        #            runs = self.experiment_queue.cleaned_automated_runs
        self.duration_tracker.load()
        dur = self._calculate_duration(runs)
        # add an empirical fudge factor
        #         ff = polyval(FUDGE_COEFFS, len(runs))

        self._total_time = dur  # + ff
        return self._total_time

    #    def calculate_etf(self):
    #        runs = self.experiment_queue.cleaned_automated_runs
    #        dur = self._calculate_duration(runs)
    #        self._total_time = dur
    #        self.etf = self.format_duration(dur)

    def format_duration(self, dur):
        post = self._post
        if not post:
            post = datetime.now()

        dt = post + timedelta(seconds=int(dur))
        return dt.strftime("%I:%M:%S %p %a %m/%d")

    def _calculate_duration(self, runs):

        dur = 0
        if runs:
            script_ctx = dict()
            warned = []
            ni = len(runs)

            run_dur = 0
            for a in runs:
                sh = a.script_hash
                if sh in self.duration_tracker:
                    run_dur += self.duration_tracker[sh]
                else:
                    run_dur += a.get_estimated_duration(script_ctx, warned, True)

            # run_dur = sum([a.get_estimated_duration(script_ctx, warned, True) for a in runs])

            btw = self.delay_between_analyses * (ni - 1)
            dur = run_dur + btw + self.delay_before_analyses
            self.debug("nruns={} before={}, run_dur={}, btw={}".format(ni, self.delay_before_analyses, run_dur, btw))

        return dur

    def _get_run_elapsed(self):
        return str(timedelta(seconds=self._run_elapsed))

    def _get_elapsed(self):
        return str(timedelta(seconds=self._elapsed))

    def _get_total_time(self):
        dur = timedelta(seconds=round(self._total_time))
        return str(dur)

    # def traits_view(self):
    #     v = View(VGroup(Readonly('nruns', label='Total Runs'),
    #                     Readonly('nruns_finished', label='Completed'),
    #                     Readonly('total_time'),
    #                     Readonly('start_at'),
    #                     Readonly('end_at'),
    #                     Readonly('run_duration'),
    #                     Readonly('current_run_duration', ),
    #                     Readonly('etf', label='Est. finish'),
    #                     Readonly('elapsed'),
    #                     Readonly('run_elapsed'),
    #                     show_border=True))
    #     return v

    def start_timer(self):
        st = time.time()
        self._post = datetime.now()

        def update_time():
            e = round(time.time() - st)
            d = {"_elapsed": e}
            if self._run_start:
                re = round(time.time() - self._run_start)
                d["_run_elapsed"] = re
            self.trait_set(**d)

        self._timer = Timer(1000, update_time)
        self._timer.start()

    def stop_timer(self):
        self.debug("Stop timer. self._timer: {}".format(self._timer))
        if self._timer:
            tt = self._total_time
            et = self._elapsed
            dt = tt - et
            self.info("Estimated total time= {:0.1f}, elapsed time= {:0.1f}, deviation= {:0.1f}".format(tt, et, dt))
            self._timer.stop()

    def reset(self):
        # self._start_time = None
        self._post = None
        self.nruns_finished = 0
        self._elapsed = 0
        self._run_elapsed = 0
        self._run_start = 0

    def update_run_duration(self, run, t):
        a = self.duration_tracker
        a.update(run.spec.script_hash, t)

    def start_run(self, run):
        self._run_start = time.time()
        self.setup_run_clock(run)

        self.current_run_duration = self.get_run_duration(run.spec, as_str=True)

    def get_run_duration(self, run, as_str=False):
        sh = run.script_hash
        if sh in self.duration_tracker:
            self.debug("using duration tracker value")
            rd = self.duration_tracker[sh]
        else:
            rd = run.get_estimated_duration(force=True)
        rd = round(rd)
        if as_str:
            rd = str(timedelta(seconds=rd))

        self.debug("run duration: {}".format(rd))
        return rd

    def finish_run(self):
        self._run_start = 0
        self.nruns_finished += 1
        if self.clock:
            self.clock.stop()

    def continue_run(self):
        if self.clock:
            self.clock.finish_slice()

    def setup_run_clock(self, run):
        if self.use_clock:
            ctx = run.spec.make_script_context()
            extraction_slice = run.extraction_script.calculate_estimated_duration(ctx)
            measurement_slice = run.measurement_script.calculate_estimated_duration(ctx)

            def convert_hexcolor_to_int(c):
                c = c[1:]
                func = lambda i: int(c[i : i + 2], 16)
                return map(func, (0, 2, 4))

            ec, mc = map(convert_hexcolor_to_int, (EXTRACTION_COLOR, MEASUREMENT_COLOR))

            self.clock.set_slices([extraction_slice, measurement_slice], [ec, mc])
            self.clock.start()
Example #22
0
class ExperimentStats(Loggable):
    elapsed = Property(depends_on='_elapsed')
    _elapsed = Float

    run_elapsed = Property(depends_on='_run_elapsed')
    _run_elapsed = Float

    remaining = Property(depends_on='_elapsed, _total_time')

    nruns = Int
    nruns_finished = Int
    etf = String
    start_at = String
    end_at = String
    run_duration = String
    current_run_duration = String
    total_time = Property(depends_on='_total_time')
    _total_time = Float

    _timer = Any

    delay_between_analyses = Float
    delay_before_analyses = Float
    delay_after_blank = Float
    delay_after_air = Float
    # _start_time = None
    _post = None

    use_clock = Bool(False)
    clock = Instance(PieClockModel, ())
    duration_tracker = Instance(AutomatedRunDurationTracker, ())
    _run_start = 0

    # experiment_queue = Any

    def calculate_duration(self, runs=None):
        self.duration_tracker.load()
        dur = self._calculate_duration(runs)
        self._total_time = dur
        return self._total_time

    def format_duration(self, dur, post=None, fmt='%H:%M:%S %a %m/%d'):
        if post is None:
            post = self._post
            if not post:
                post = datetime.now()

        dt = post + timedelta(seconds=int(dur))
        if fmt == 'iso':
            return dt.isoformat()
        else:
            return dt.strftime(fmt)

    def start_timer(self):
        st = time.time()
        self._post = datetime.now()

        def update_time():
            e = round(time.time() - st)
            d = {'_elapsed': e}
            if self._run_start:
                re = round(time.time() - self._run_start)
                d['_run_elapsed'] = re
            self.trait_set(**d)

        self._timer = Timer(1000, update_time)
        self._timer.start()

    def stop_timer(self):
        self.debug('Stop timer. self._timer: {}'.format(self._timer))
        if self._timer:
            tt = self._total_time
            et = self._elapsed
            dt = tt - et
            self.info('Estimated total time= {:0.1f}, elapsed time= {:0.1f}, deviation= {:0.1f}'.format(tt, et, dt))
            self._timer.stop()

    def reset(self):
        # self._start_time = None
        self._post = None
        self.nruns_finished = 0
        self._elapsed = 0
        self._run_elapsed = 0
        self._run_start = 0

    def update_run_duration(self, run, t):
        a = self.duration_tracker
        a.update(run, t)

    def start_run(self, run):
        self._run_start = time.time()
        self.setup_run_clock(run)

        self.current_run_duration = self.get_run_duration(run.spec, as_str=True)

    def get_run_duration(self, run, as_str=False):
        sh = run.script_hash
        if sh in self.duration_tracker:
            self.debug('using duration tracker value')
            rd = self.duration_tracker[sh]
        else:
            rd = run.get_estimated_duration(force=True)
        rd = round(rd)
        if as_str:
            rd = str(timedelta(seconds=rd))

        self.debug('run duration: {}'.format(rd))
        return rd

    def finish_run(self):
        self._run_start = 0
        self.nruns_finished += 1
        self.debug('finish run. runs completed={}'.format(self.nruns_finished))
        if self.clock:
            self.clock.stop()

    def continue_run(self):
        if self.clock:
            self.clock.finish_slice()

    def setup_run_clock(self, run):
        if self.use_clock:
            ctx = run.spec.make_script_context()
            extraction_slice = run.extraction_script.calculate_estimated_duration(ctx)
            measurement_slice = run.measurement_script.calculate_estimated_duration(ctx)

            def convert_hexcolor_to_int(c):
                c = c[1:]
                # func = lambda i: int(c[i:i + 2], 16)
                # return list(map(func, (0, 2, 4)))
                return [int(c[i:i + 2], 16) for i in (0, 2, 4)]

            # ec, mc = list(map(convert_hexcolor_to_int,
            #                   (EXTRACTION_COLOR, MEASUREMENT_COLOR)))
            ec, mc = convert_hexcolor_to_int(EXTRACTION_COLOR), convert_hexcolor_to_int(MEASUREMENT_COLOR)
            self.clock.set_slices([extraction_slice, measurement_slice],
                                  [ec, mc])
            self.clock.start()

    # private
    def _calculate_duration(self, runs):

        dur = 0
        if runs:
            script_ctx = dict()
            warned = []
            ni = len(runs)

            btw = 0
            run_dur = 0
            d = 0
            for a in runs:
                sh = a.script_hash

                if sh in self.duration_tracker:
                    # t = a.make_truncated_script_hash()
                    # if a.has_conditionals() and t in self.duration_tracker:
                    #     run_dur += self.duration_tracker.probability_model(sh, t)
                    # else:
                    #     run_dur += self.duration_tracker[sh]
                    run_dur += self.duration_tracker[sh]
                else:
                    run_dur += a.get_estimated_duration(script_ctx, warned, True)
                d = a.get_delay_after(self.delay_between_analyses, self.delay_after_blank, self.delay_after_air)
                btw += d

            # subtract the last delay_after because experiment doesn't delay after last analysis
            btw -= d

            dur = run_dur + self.delay_before_analyses + btw
            self.debug('nruns={} before={}, run_dur={}, btw={}'.format(ni, self.delay_before_analyses,
                                                                       run_dur, btw))

        return dur

    def _get_run_elapsed(self):
        return str(timedelta(seconds=self._run_elapsed))

    def _get_elapsed(self):
        return str(timedelta(seconds=self._elapsed))

    def _get_total_time(self):
        dur = timedelta(seconds=round(self._total_time))
        return str(dur)

    def _get_remaining(self):
        if not self._total_time:
            dur = NULL_STR
        else:
            dur = timedelta(seconds=round(self._total_time - self._elapsed))
        return str(dur)
Example #23
0
class ExperimentStats(Loggable):
    elapsed = Property(depends_on='_elapsed')
    _elapsed = Float

    run_elapsed = Property(depends_on='_run_elapsed')
    _run_elapsed = Float

    remaining = Property(depends_on='_elapsed, _total_time')

    nruns = Int
    nruns_finished = Int
    etf = String
    start_at = String
    end_at = String
    run_duration = String
    current_run_duration = String
    total_time = Property(depends_on='_total_time')
    _total_time = Float

    _timer = Any

    delay_between_analyses = Float
    delay_before_analyses = Float
    # _start_time = None
    _post = None

    use_clock = Bool(False)
    clock = Instance(PieClockModel, ())
    duration_tracker = Instance(AutomatedRunDurationTracker, ())
    _run_start = 0

    # experiment_queue = Any

    def calculate_duration(self, runs=None):
        self.duration_tracker.load()
        dur = self._calculate_duration(runs)
        self._total_time = dur
        return self._total_time

    def format_duration(self, dur, post=None):
        if post is None:
            post = self._post
            if not post:
                post = datetime.now()

        dt = post + timedelta(seconds=int(dur))
        return dt.strftime('%H:%M:%S %a %m/%d')

    def start_timer(self):
        st = time.time()
        self._post = datetime.now()

        def update_time():
            e = round(time.time() - st)
            d = {'_elapsed': e}
            if self._run_start:
                re = round(time.time() - self._run_start)
                d['_run_elapsed'] = re
            self.trait_set(**d)

        self._timer = Timer(1000, update_time)
        self._timer.start()

    def stop_timer(self):
        self.debug('Stop timer. self._timer: {}'.format(self._timer))
        if self._timer:
            tt = self._total_time
            et = self._elapsed
            dt = tt - et
            self.info(
                'Estimated total time= {:0.1f}, elapsed time= {:0.1f}, deviation= {:0.1f}'
                .format(tt, et, dt))
            self._timer.stop()

    def reset(self):
        # self._start_time = None
        self._post = None
        self.nruns_finished = 0
        self._elapsed = 0
        self._run_elapsed = 0
        self._run_start = 0

    def update_run_duration(self, run, t):
        a = self.duration_tracker
        a.update(run, t)

    def start_run(self, run):
        self._run_start = time.time()
        self.setup_run_clock(run)

        self.current_run_duration = self.get_run_duration(run.spec,
                                                          as_str=True)

    def get_run_duration(self, run, as_str=False):
        sh = run.script_hash
        if sh in self.duration_tracker:
            self.debug('using duration tracker value')
            rd = self.duration_tracker[sh]
        else:
            rd = run.get_estimated_duration(force=True)
        rd = round(rd)
        if as_str:
            rd = str(timedelta(seconds=rd))

        self.debug('run duration: {}'.format(rd))
        return rd

    def finish_run(self):
        self._run_start = 0
        self.nruns_finished += 1
        self.debug('finish run. runs completed={}'.format(self.nruns_finished))
        if self.clock:
            self.clock.stop()

    def continue_run(self):
        if self.clock:
            self.clock.finish_slice()

    def setup_run_clock(self, run):
        if self.use_clock:
            ctx = run.spec.make_script_context()
            extraction_slice = run.extraction_script.calculate_estimated_duration(
                ctx)
            measurement_slice = run.measurement_script.calculate_estimated_duration(
                ctx)

            def convert_hexcolor_to_int(c):
                c = c[1:]
                func = lambda i: int(c[i:i + 2], 16)
                return map(func, (0, 2, 4))

            ec, mc = map(convert_hexcolor_to_int,
                         (EXTRACTION_COLOR, MEASUREMENT_COLOR))

            self.clock.set_slices([extraction_slice, measurement_slice],
                                  [ec, mc])
            self.clock.start()

    # private
    def _calculate_duration(self, runs):

        dur = 0
        if runs:
            script_ctx = dict()
            warned = []
            ni = len(runs)

            run_dur = 0
            for a in runs:
                sh = a.script_hash

                if sh in self.duration_tracker:
                    t = a.make_truncated_script_hash()
                    if a.has_conditionals() and t in self.duration_tracker:
                        run_dur += self.duration_tracker.probability_model(
                            sh, t)
                    else:
                        run_dur += self.duration_tracker[sh]
                else:
                    run_dur += a.get_estimated_duration(
                        script_ctx, warned, True)

            btw = self.delay_between_analyses * (ni - 1)
            dur = run_dur + btw + self.delay_before_analyses
            self.debug('nruns={} before={}, run_dur={}, btw={}'.format(
                ni, self.delay_before_analyses, run_dur, btw))

        return dur

    def _get_run_elapsed(self):
        return str(timedelta(seconds=self._run_elapsed))

    def _get_elapsed(self):
        return str(timedelta(seconds=self._elapsed))

    def _get_total_time(self):
        dur = timedelta(seconds=round(self._total_time))
        return str(dur)

    def _get_remaining(self):
        dur = timedelta(seconds=round(self._total_time - self._elapsed))
        return str(dur)
Example #24
0
class ExperimentStats(Loggable):
    elapsed = Property(depends_on='_elapsed')
    _elapsed = Float
    nruns = Int
    nruns_finished = Int
    etf = String
    time_at = String
    total_time = Property(depends_on='_total_time')
    _total_time = Float

    _timer = Any

    delay_between_analyses = Float
    delay_before_analyses = Float
    _start_time = None

    use_clock = Bool(False)
    clock = Instance(PieClockModel, ())
    #    experiment_queue = Any

    def calculate_duration(self, runs=None):
        #        if runs is None:
        #            runs = self.experiment_queue.cleaned_automated_runs
        dur = self._calculate_duration(runs)
        # add an empirical fudge factor
        #         ff = polyval(FUDGE_COEFFS, len(runs))

        self._total_time = dur  # + ff
        return self._total_time

    #    def calculate_etf(self):
    #        runs = self.experiment_queue.cleaned_automated_runs
    #        dur = self._calculate_duration(runs)
    #        self._total_time = dur
    #        self.etf = self.format_duration(dur)

    def format_duration(self, dur):
        dt = (datetime.datetime.now() + \
              datetime.timedelta(seconds=int(dur)))
        return dt.strftime('%I:%M:%S %p %a %m/%d')

    def _calculate_duration(self, runs):
        dur = 0
        if runs:
            script_ctx = dict()
            warned = []
            ni = len(runs)
            run_dur = sum([a.get_estimated_duration(script_ctx, warned, True) for a in runs])

            btw = self.delay_between_analyses * (ni - 1)
            dur = run_dur + btw + self.delay_before_analyses
            self.debug('before={}, run_dur={}, btw={}'.format(self.delay_before_analyses,
                                                              run_dur, btw))

        return dur

    def _get_elapsed(self):
        return str(datetime.timedelta(seconds=self._elapsed))

    def _get_total_time(self):
        dur = datetime.timedelta(seconds=round(self._total_time))
        return str(dur)

    def traits_view(self):
        v = View(VGroup(
            Item('nruns',
                 label='Total Runs',
                 style='readonly'),
            Item('nruns_finished',
                 label='Completed',
                 style='readonly'),
            Item('total_time',
                 style='readonly'),
            Item('time_at', style='readonly'),
            Item('etf', style='readonly', label='Est. finish'),
            Item('elapsed',
                 style='readonly')),
                 UItem('clock', style='custom', width=100, height=100, defined_when='use_clock'))
        return v

    def start_timer(self):
        st = time.time()
        self._start_time = st

        def update_time():
            e = round(time.time() - st)
            self.trait_set(_elapsed=e)

        self._timer = Timer(1000, update_time)
        self._timer.start()

    def stop_timer(self):
        if self._timer:
            tt = self._total_time
            et = self._elapsed
            dt = tt - et
            self.info('Estimated total time= {:0.1f}, elapsed time= {:0.1f}, deviation= {:0.1f}'.format(tt, et, dt))
            self._timer.stop()

    def reset(self):
        self._start_time = None
        self.nruns_finished = 0
        self._elapsed = 0

    def finish_run(self):
        self.nruns_finished += 1
        if self.clock:
            self.clock.stop()

    def continue_run(self):
        if self.clock:
            self.clock.finish_slice()

    def setup_run_clock(self, run):
        if self.use_clock:
            ctx = run.spec.make_script_context()
            extraction_slice = run.extraction_script.calculate_estimated_duration(ctx)
            measurement_slice = run.measurement_script.calculate_estimated_duration(ctx)

            def convert_hexcolor_to_int(c):
                c = c[1:]
                func = lambda i: int(c[i:i + 2], 16)
                return map(func, (0, 2, 4))

            ec, mc = map(convert_hexcolor_to_int,
                         (EXTRACTION_COLOR, MEASUREMENT_COLOR))

            self.clock.set_slices([extraction_slice, measurement_slice],
                                  [ec, mc])
            self.clock.start()
Example #25
0
class ExperimentStats(Loggable):
    elapsed = Property(depends_on='_elapsed')
    _elapsed = Float
    nruns = Int
    nruns_finished = Int
    etf = String
    time_at = String
    total_time = Property(depends_on='_total_time')
    _total_time = Float

    _timer = Any

    delay_between_analyses = Float
    delay_before_analyses = Float
    _start_time = None

#    experiment_queue = Any

    def calculate_duration(self, runs=None):
#        if runs is None:
#            runs = self.experiment_queue.cleaned_automated_runs
        dur = self._calculate_duration(runs)
        # add an empirical fudge factor
#         ff = polyval(FUDGE_COEFFS, len(runs))

        self._total_time = dur  # + ff
        return self._total_time

#    def calculate_etf(self):
#        runs = self.experiment_queue.cleaned_automated_runs
#        dur = self._calculate_duration(runs)
#        self._total_time = dur
#        self.etf = self.format_duration(dur)

    def format_duration(self, dur):
        dt = (datetime.datetime.now() + \
                       datetime.timedelta(seconds=int(dur)))
        return dt.strftime('%I:%M:%S %p %a %m/%d')

    def _calculate_duration(self, runs):
        dur = 0
        if runs:
            script_ctx = dict()
            warned = []
            ni = len(runs)
            dur = sum([a.get_estimated_duration(script_ctx, warned) for a in runs])

            btw = (self.delay_between_analyses * ni)
            dur += btw + self.delay_before_analyses

        return dur

    def _get_elapsed(self):
        return str(datetime.timedelta(seconds=self._elapsed))

    def _get_total_time(self):
        dur = datetime.timedelta(seconds=round(self._total_time))
        return str(dur)

    def traits_view(self):
        v = View(VGroup(
                        Item('nruns',
                            label='Total Runs',
                            style='readonly'
                            ),
                        Item('nruns_finished',
                             label='Completed',
                             style='readonly'
                             ),
                        Item('total_time',
                              style='readonly'),
                        Item('time_at', style='readonly'),
                        Item('etf', style='readonly', label='Est. finish'),
                        Item('elapsed',
                             style='readonly'),
                        )
                 )
        return v

    def start_timer(self):
        st = time.time()
        self._start_time = st
        def update_time():
            e = round(time.time() - st)
            self.trait_set(_elapsed=e)

        self._timer = Timer(1000, update_time)
        self._timer.start()

    def stop_timer(self):
        if self._timer:
            tt = self._total_time
            et = self._elapsed
            dt = tt - et
            self.info('Estimated total time= {:0.1f}, elapsed time= {:0.1f}, deviation= {:0.1f}'.format(tt, et, dt))
            self._timer.stop()

    def reset(self):
        self._start_time = None
        self.nruns_finished = 0
        self._elapsed = 0