Example #1
0
 def traits_view(self):
     v = View(UItem('canvas', style='custom'))
     return v
Example #2
0
class UpdateView(HasTraits):
    piksi_hw_rev = String('piksi_multi')
    is_v2 = Bool(False)

    piksi_stm_vers = String(
        'Waiting for Piksi to send settings...', width=COLUMN_WIDTH)
    newest_stm_vers = String('Downloading Latest Firmware info...')
    piksi_nap_vers = String('Waiting for Piksi to send settings...')
    newest_nap_vers = String('Downloading Latest Firmware info...')
    local_console_vers = String(CONSOLE_VERSION)
    newest_console_vers = String('Downloading Latest Console info...')
    download_directory_label = String('Firmware Download Directory:')

    update_stm_firmware = Button(label='Update Firmware')

    updating = Bool(False)
    update_stm_en = Bool(False)

    download_firmware = Button(label='Download Latest Firmware')
    download_directory = Unicode()
    choose_dir = Button(label='...', padding=-1)
    download_stm = Button(label='Download', height=HT)
    downloading = Bool(False)
    download_fw_en = Bool(False)

    stm_fw = Instance(FirmwareFileDialog)

    stream = Instance(OutputStream)

    local_file_for_fileio = String()
    choose_local_file = Button(label='...', padding=-1)
    destination_path_for_fileio = '/persistent/licenses/smoothpose_license.json'
    send_file_to_device = Button()

    view = View(
        VGroup(
            Item(
                'piksi_hw_rev',
                label='Hardware Revision',
                editor_args={'enabled': False},
                resizable=True),
            HGroup(
                VGroup(
                    Item(
                        'piksi_stm_vers',
                        label='Current',
                        resizable=True,
                        editor_args={'enabled': False}),
                    Item(
                        'newest_stm_vers',
                        label='Latest',
                        resizable=True,
                        editor_args={
                            'enabled': False,
                            'readonly_allow_selection': True
                        }),
                    Item(
                        'stm_fw',
                        style='custom',
                        show_label=True,
                        label="Local File"),
                    Item(
                        'update_stm_firmware',
                        show_label=False,
                        enabled_when='update_stm_en'),

                    show_border=True,
                    label="Firmware Version"),
                VGroup(
                    HGroup(
                        Item('download_directory', label="Directory", resizable=True),
                        UItem('choose_dir', width=-0.1),
                    ),
                    HGroup(
                        Spring(width=50, springy=False),
                        Item('download_firmware', enabled_when='download_fw_en',
                             show_label=False, resizable=True, springy=True)
                    ),
                    label="Firmware Download",
                    show_border=True)
            ),
            HGroup(
                VGroup(
                    Item(
                        'stream',
                        style='custom',
                        editor=InstanceEditor(),
                        show_label=False, ),
                    show_border=True,
                    label="Firmware Upgrade Status"),
            ),
            HGroup(
                Item('local_file_for_fileio', label="Local File"),
                Item('choose_local_file', show_label=False),
                Item('destination_path_for_fileio', label="Destination Path"),
                Item("send_file_to_device", show_label=False),
                show_border=True,
                label="File IO and product feature unlock tool"
            )
        )
    )

    def __init__(self,
                 link,
                 download_dir=None,
                 prompt=True,
                 connection_info={'mode': 'unknown'}):
        """
        Traits tab with UI for updating Piksi firmware.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        prompt : bool
          Prompt user to update console/firmware if out of date.
        """
        self.link = link
        self.connection_info = connection_info
        self.settings = {}
        self.nw_chk = NetworkCheck(self._write, self.set_download_fw_en)
        self.prompt = prompt
        self.python_console_cmds = {'update': self}
        self.download_directory = download_dir
        try:
            self.update_dl = UpdateDownloader(root_dir=self.download_directory)
        except RuntimeError:
            self.update_dl = None
        self.stm_fw = FirmwareFileDialog(self.download_directory)
        self.stm_fw.on_trait_change(self._manage_enables, 'status')
        self.stream = OutputStream()
        self.stream.max_len = 1000
        self.last_call_fw_version = None
        self.link.add_callback(self.log_cb, SBP_MSG_LOG)

    def set_download_fw_en(self, value):
        self.download_fw_en = value

    def _choose_dir_fired(self):
        dialog = DirectoryDialog(
            label='Choose Download location',
            action='open',
            default_directory=self.download_directory)
        dialog.open()
        if dialog.return_code == OK:
            self.download_directory = dialog.path
        else:
            self._write('Error while selecting firmware download location')

    def _send_file(self):
        blob = open(self.local_file_for_fileio, 'rb').read()
        self.blob_size = float(len(blob))
        self.pcent_complete = 0
        FileIO(self.link).write(bytes(self.destination_path_for_fileio, 'ascii'),
                                blob,
                                progress_cb=self.file_transfer_progress_cb)

    def _send_file_to_device_fired(self):
        self._write("Initiating file transfer of {} to location {}".format(
            self.local_file_for_fileio, self.destination_path_for_fileio))
        if not os.path.isfile(self.local_file_for_fileio):
            self._write("Error with path: {} is not a file".format(self.local_file_for_fileio))
            return
        else:
            self._send_file_thread = Thread(target=self._send_file)
            self._send_file_thread.start()

    def _choose_local_file_fired(self):
        dialog = FileDialog(
            label='Choose local_file',
            action='open')
        dialog.open()
        if dialog.return_code == OK:
            self.local_file_for_fileio = dialog.path
        else:
            self._write('Error while selecting local file.')

    def _manage_enables(self):
        """ Manages whether traits widgets are enabled in the UI or not. """
        if self.updating or self.downloading:
            self.update_stm_en = False
            self.download_fw_en = False
        else:
            if getattr(self.stm_fw, 'blob', None) is not None:
                self.update_stm_en = True
            else:
                self.update_stm_en = False
            if self.download_directory != '':
                self.download_fw_en = True

    def _download_directory_changed(self):
        if getattr(self, 'update_dl', None):
            self.update_dl.set_root_path(self.download_directory)
        self._manage_enables()

    def _updating_changed(self):
        """ Handles self.updating trait being changed. """
        self._manage_enables()

    def _downloading_changed(self):
        """ Handles self.downloading trait being changed. """
        self._manage_enables()

    def _clear_stream(self):
        self.stream.reset()

    def _write(self, text):
        """
        Stream style write function. Allows flashing debugging messages to be
        routed to embedded text console.

        Parameters
        ----------
        text : string
          Text to be written to screen.
        """
        self.stream.write(text)
        self.stream.write('\n')
        self.stream.flush()

    def _update_stm_firmware_fired(self):
        """
        Handle update_stm_firmware button. Starts thread so as not to block the GUI
        thread.
        """
        if self.connection_info['mode'] != 'TCP/IP':
            self._write(
                "\n"
                "-----------------------------------------------\n"
                "USB Flashdrive Upgrade Procedure\n"
                "-----------------------------------------------\n"
                "\n"
                "1.\tInsert the USB flash drive provided with your Piksi Multi into your computer.\n"
                "  \tSelect the flash drive root directory as the firmware download destination using the directory chooser above.\n"
                "  \tPress the \"Download Latest Firmware\" button. This will download the latest Piksi Multi firmware file onto\n"
                "  \tthe USB flashdrive.\n"
                "2.\tEject the drive from your computer and plug it into the USB Host port of the Piksi Multi evaluation board.\n"
                "3.\tReset your Piksi Multi and it will upgrade to the version on the USB flash drive.\n"
                "  \tThis should take less than 5 minutes.\n"
                "4.\tWhen the upgrade completes you will be prompted to remove the USB flash drive and reset your Piksi Multi.\n"
                "5.\tVerify that the firmware version has upgraded via inspection of the Current Firmware Version box\n"
                "  \ton the Update Tab of the Swift Console.\n")

            confirm_prompt = prompt.CallbackPrompt(
                title="Update device over serial connection?",
                actions=[prompt.close_button, prompt.continue_via_serial_button],
                callback=self._update_stm_firmware_fn)
            confirm_prompt.text = "\n" \
                                  + "    Upgrading your device via UART / RS232 may take up to 30 minutes.     \n" \
                                  + "                                                                          \n" \
                                  + "    If the device you are upgrading has an accessible USB host port, it   \n" \
                                    "    is recommended to instead  follow the \'USB Flashdrive Upgrade        \n" \
                                    "    Procedure\' that now appears in the Firmware upgrade status box.      \n" \
                                  + "\n" \
                                  + "    Are you sure you want to continue upgrading over serial?"
            confirm_prompt.run(block=False)
        else:
            self._update_stm_firmware_fn()

    def _replace_with_version_2(self):
        if not self.nw_chk.network_is_reachable():
            return

        self.downloading = True
        self._write('Downloading Multi firmware v2.0.0')
        filepath = self.update_dl._download_file_from_url(V2_LINK)
        self._write('Saved file to %s' % filepath)
        self.stm_fw.load_bin(filepath)
        self.downloading = False

    def _update_stm_firmware_fn(self):
        try:
            if self._firmware_update_thread.is_alive():
                return
        except AttributeError:
            pass

        current_fw_version = parse_version(self.piksi_stm_vers)
        re_result = re.search('.*-(v[0-9]*\.[0-9]*\.[0-9]*.*).bin$', self.stm_fw.status)
        intended_version = parse_version(str(re_result.group(1)))
        # If the current firmware is not yet beyond 2.0.0, and we are loading beyond 2.0.0
        # warn the user that this upgrade is not possible. But always allow development version
        if (current_fw_version.isdev is False) and (intended_version.isdev is False) and (current_fw_version < parse_version("v2.0.0")) and (intended_version > parse_version("v2.0.0")):
            confirm_prompt = prompt.CallbackPrompt(
                title="Update to v2.0.0",
                actions=[prompt.close_button, prompt.ok_button],
                callback=self._replace_with_version_2)
            confirm_prompt.text = "\n" \
                                  + "    Upgrading to firmware v2.1.0 or later requires that the device be     \n" \
                                  + "    running firmware v2.0.0 or later. Please upgrade to firmware          \n" \
                                  + "    version 2.0.0.                                                        \n" \
                                  + "                                                                          \n" \
                                  + "    Would you like to download firmware version v2.0.0 now?               \n" \
                                  + "                                                                          \n"
            confirm_prompt.run(block=False)
            return
        self._firmware_update_thread = Thread(
            target=self.manage_firmware_updates, args=("STM",))
        self._firmware_update_thread.start()

    def _download_firmware(self):
        """ Download latest firmware from swiftnav.com. """
        if not self.nw_chk.network_is_reachable():
            return

        self._write('')

        # Check that we received the index file from the website.
        if self.update_dl is None or self.update_dl.index is None:
            self._write("Error: Can't download firmware files")
            return

        self.downloading = True
        status = 'Downloading Latest Firmware...'
        self.stm_fw.clear(status)
        self._write(status)

        # Get firmware files from Swift Nav's website, save to disk, and load.
        if 'fw' in self.update_dl.index[self.piksi_hw_rev]:
            try:
                self._write('Downloading Latest Multi firmware')
                filepath = self.update_dl.download_multi_firmware(
                    self.piksi_hw_rev)
                self._write('Saved file to %s' % filepath)
                self.stm_fw.load_bin(filepath)
            except AttributeError:
                self._write(
                    "Error downloading firmware: index file not downloaded yet"
                )
            except RuntimeError as e:
                self._write(
                    "RunTimeError: unable to download firmware to path {0}: {1}".format(self.download_directory, e))
            except IOError as e:
                if e.errno == errno.EACCES or e.errno == errno.EPERM:
                    self._write("IOError: unable to write to path %s. "
                                "Verify that the path is writable." %
                                self.download_directory)
                else:
                    raise (e)
            except KeyError:
                self._write(
                    "Error downloading firmware: URL not present in index")
            except URLError:
                self.nap_fw.clear("Error downloading firmware")
                self._write(
                    "Error: Failed to download latest NAP firmware from Swift Navigation's website"
                )
            self.downloading = False
            return

    def _download_firmware_fired(self):
        """
        Handle download_firmware button. Starts thread so as not to block the GUI
        thread.
        """
        try:
            if self._download_firmware_thread.is_alive():
                return
        except AttributeError:
            pass

        self._download_firmware_thread = Thread(target=self._download_firmware)
        self._download_firmware_thread.start()

    def compare_versions(self):
        """
        To be called after latest Piksi firmware info has been received from
        device, to decide if current firmware on Piksi is out of date. Also informs
        user if the firmware was successfully upgraded. Starts a thread so as not
        to block GUI thread.
        """
        try:
            if self._compare_versions_thread.is_alive():
                return
        except AttributeError:
            pass

        self._compare_versions_thread = Thread(target=self._compare_versions)
        self._compare_versions_thread.start()

    def _compare_versions(self):
        """
        Compares version info between received firmware version / current console
        and firmware / console info from website to decide if current firmware or
        console is out of date. Prompt user to update if so. Informs user if
        firmware successfully upgraded.
        """
        # Check that settings received from Piksi contain FW versions.
        try:
            self.piksi_hw_rev = HW_REV_LOOKUP[self.settings['system_info']['hw_revision'].value]
            self.piksi_stm_vers = self.settings['system_info']['firmware_version'].value
        except KeyError:
            self._write(
                "\nWarning: Settings received from Piksi do not contain firmware version information. Unable to determine software update status.\n"
            )
            return

        self.is_v2 = self.piksi_hw_rev.startswith('piksi_v2')

        self._get_latest_version_info()

        # Check that we received the index file from the website.
        if self.update_dl is None:
            self._write(
                "\nWarning: Unable to fetch firmware release index from Swift to determine update status.\n"
            )
            return
        # Get local stm version
        local_stm_version = None
        local_serial_number = None
        try:
            local_stm_version = self.settings['system_info'][
                'firmware_version'].value
            local_serial_number = self.settings['system_info'][
                'serial_number'].value
        except:  # noqa
            pass
        # Check if console is out of date and notify user if so.
        if self.prompt:
            local_console_version = parse_version(CONSOLE_VERSION)
            remote_console_version = parse_version(self.newest_console_vers)
            self.console_outdated = remote_console_version > local_console_version

            # we want to warn users using v2 regardless of version logic
            if self.console_outdated or self.is_v2:
                if not self.is_v2:
                    console_outdated_prompt = \
                        prompt.CallbackPrompt(
                            title="Swift Console Outdated",
                            actions=[prompt.close_button],
                        )
                    console_outdated_prompt.text = \
                        "Your console is out of date and may be incompatible\n" + \
                        "with current firmware. We highly recommend upgrading to\n" + \
                        "ensure proper behavior.\n\n" + \
                        "Please visit http://support.swiftnav.com to\n" + \
                        "download the latest version.\n\n" + \
                        "Local Console Version :\n\t" + \
                        CONSOLE_VERSION + \
                        "\nLatest Console Version :\n\t" + \
                        self.update_dl.index[self.piksi_hw_rev]['console']['version'] + "\n"
                else:
                    console_outdated_prompt = \
                        prompt.CallbackPrompt(
                            title="Swift Console Incompatible",
                            actions=[prompt.close_button],
                        )
                    console_outdated_prompt.text = \
                        "Your console is incompatible with your hardware revision.\n" + \
                        "We highly recommend using a compatible console version\n" + \
                        "to ensure proper behavior.\n\n" + \
                        "Please visit http://support.swiftnav.com to\n" + \
                        "download the latest compatible version.\n\n" + \
                        "Current Hardware revision :\n\t" + \
                        self.piksi_hw_rev + \
                        "\nLast supported Console Version: \n\t" + \
                        self.update_dl.index[self.piksi_hw_rev]['console']['version'] + "\n"

                console_outdated_prompt.run()

            # For timing aesthetics between windows popping up.
            sleep(0.5)

            # Check if firmware is out of date and notify user if so.
            remote_stm_version = self.newest_stm_vers

            self.fw_outdated = remote_stm_version > local_stm_version
            if local_stm_version.startswith('DEV'):
                self.fw_outdated = False

            if self.fw_outdated:
                fw_update_prompt = \
                    prompt.CallbackPrompt(
                        title='Firmware Update',
                        actions=[prompt.close_button]
                    )

                if 'fw' in self.update_dl.index[self.piksi_hw_rev]:
                    fw_update_prompt.text = \
                        "New Piksi firmware available.\n\n" + \
                        "Please use the Update tab to update.\n\n" + \
                        "Newest Firmware Version :\n\t%s\n\n" % \
                        self.update_dl.index[self.piksi_hw_rev]['fw']['version']
                else:
                    fw_update_prompt.text = \
                        "New Piksi firmware available.\n\n" + \
                        "Please use the Update tab to update.\n\n" + \
                        "Newest STM Version :\n\t%s\n\n" % \
                        self.update_dl.index[self.piksi_hw_rev]['stm_fw']['version'] + \
                        "Newest SwiftNAP Version :\n\t%s\n\n" % \
                        self.update_dl.index[self.piksi_hw_rev]['nap_fw']['version']

                fw_update_prompt.run()

        # Check if firmware successfully upgraded and notify user if so.
        if ((self.last_call_fw_version is not None and self.last_call_fw_version != local_stm_version) and
                (self.last_call_sn is None or local_serial_number is None or self.last_call_sn == local_serial_number)):
            fw_success_str = "Firmware successfully upgraded from %s to %s." % \
                             (self.last_call_fw_version, local_stm_version)
            print(fw_success_str)
            self._write(fw_success_str)

        # Record firmware version reported each time this callback is called.
        self.last_call_fw_version = local_stm_version
        self.last_call_sn = local_serial_number

    def _get_latest_version_info(self):
        """ Get latest firmware / console version from website. """
        self.update_dl = None

        if not self.nw_chk.network_is_reachable():
            return

        try:
            self.update_dl = UpdateDownloader(root_dir=self.download_directory)
        except RuntimeError:
            self._write(
                "\nError: Failed to download latest file index from Swift Navigation's website. Please visit our website to check that you're running the latest Piksi firmware and Piksi console.\n"
            )
            return

        # Make sure index contains all keys we are interested in.
        try:
            if 'fw' in self.update_dl.index[self.piksi_hw_rev]:
                self.newest_stm_vers = self.update_dl.index[self.piksi_hw_rev][
                    'fw']['version']
            else:
                self.newest_stm_vers = self.update_dl.index[self.piksi_hw_rev][
                    'stm_fw']['version']
                self.newest_nap_vers = self.update_dl.index[self.piksi_hw_rev][
                    'nap_fw']['version']
            self.newest_console_vers = self.update_dl.index[self.piksi_hw_rev][
                'console']['version']
        except KeyError:
            self._write(
                "\nError: Index downloaded from Swift Navigation's website (%s) doesn't contain all keys. Please contact Swift Navigation.\n"
                % INDEX_URL)
            return

    def file_transfer_progress_cb(self, offset, repeater):
        new_pcent = float(offset) / float(self.blob_size) * 100
        if new_pcent - self.pcent_complete > 0.1:
            self.pcent_complete = new_pcent
            self.stream.scrollback_write("{:2.1f} % of {:2.1f} MB transferred.".format(
                self.pcent_complete, self.blob_size * 1e-6))

    def log_cb(self, msg, **kwargs):
        for regex in UPGRADE_WHITELIST:
            msg_text = msg.text.decode('utf8')
            if re.match(regex, msg_text):
                text = msg_text.replace("\r", "\n").strip().split("\n")
                if len(text) > 1:
                    # upgrade tool deliminates lines in stoud with \r, we want penultimate line that is complete to show
                    text = text[-2]
                else:
                    # If there is only one line, we show that
                    text = text[-1]
                self.stream.scrollback_write(text)

    def manage_multi_firmware_update(self):
        self.blob_size = float(len(self.stm_fw.blob))
        self.pcent_complete = 0
        # Set up progress dialog and transfer file to Piksi using SBP FileIO
        self._clear_stream()
        self._write("Transferring image to device...\n\n00.0 of {:2.1f} MB trasnferred".format(
            self.blob_size * 1e-6))
        try:
            FileIO(self.link).write(
                b"upgrade.image_set.bin",
                self.stm_fw.blob,
                progress_cb=self.file_transfer_progress_cb)
        except Exception as e:
            self._write("Failed to transfer image file to Piksi: %s\n" % e)
            self._write("Upgrade Aborted.")
            import traceback
            print(traceback.format_exc())
            return -1

        self.stream.scrollback_write(
            "Image transfer complete: {:2.1f} MB transferred.\n".format(self.blob_size * 1e-6))
        # Setup up pulsed progress dialog and commit to flash
        self._write("Committing file to Flash...\n")
        self.link.add_callback(self.log_cb, SBP_MSG_LOG)
        code = shell_command(
            self.link,
            b"upgrade_tool upgrade.image_set.bin",
            200)
        self.link.remove_callback(self.log_cb, SBP_MSG_LOG)

        if code != 0:
            self._write('Failed to perform upgrade (code = %d)' % code)
            if code == -255:
                self._write('Shell command timed out.  Please try again.')
            return
        self._write("Upgrade Complete.")
        self._write('Resetting Piksi...')
        self.link(MsgReset(flags=0))

    # Executed in GUI thread, called from Handler.
    def manage_firmware_updates(self, device):
        """
        Update Piksi firmware. Erase entire STM flash (other than bootloader)
        if so directed. Flash NAP only if new firmware is available.
        """
        self.updating = True
        self._write('')
        if not self.is_v2:
            self.manage_multi_firmware_update()
        else:
            self._write('Unable to upgrade piksi v2; please use the last supported v2 console version.')
            self._write("")
        self.updating = False
Example #3
0
 def traits_view(self):
     v = View(UItem('pie_clock', width=150, height=150))
     return v
Example #4
0
class ModelView(HasTraits):

    model = Instance(Model)
    view = Instance(PlotUI)
    timer = Instance(Timer)
    timer_controller = Instance(TimerController, ())

    edit_model = Button
    edit_view = Button
    animated = Bool(False)

    # Whether to animate colors on a bounce of each side:
    animate_left = Bool(False)
    animate_right = Bool(False)
    animate_top = Bool(False)
    animate_bottom = Bool(False)

    traits_view = View(UItem('@view'),
                       HGroup(
                           UItem('edit_model', enabled_when='not animated'),
                           UItem('edit_view'), Item('animated'),
                           Item('animate_left',
                                enabled_when='animated',
                                label='Change colors at:  Left'),
                           Item('animate_right',
                                enabled_when='animated',
                                label='Right'),
                           Item('animate_top',
                                enabled_when='animated',
                                label='Top'),
                           Item('animate_bottom',
                                enabled_when='animated',
                                label='Bottom'), spring),
                       title="Function Inspector",
                       resizable=True)

    @on_trait_change('model, model.model_changed, view')
    def update_view(self):
        if self.model is not None and self.view is not None:
            self.view.update(self.model)

    def _edit_model_fired(self):
        self.model.configure_traits()

    def _edit_view_fired(self):
        self.view.configure_traits(view="plot_edit_view")

    def _start_timer(self):
        # Start up the timer! We should do this only when the demo actually
        # starts and not when the demo object is created.
        # FIXME: close timer on exit.
        self.timer_controller.view = self.view
        self.timer_controller.model_view = self
        self.timer = Timer(40, self.timer_controller.onTimer)

    def edit_traits(self, *args, **kws):
        self._start_timer()
        return super(ModelView, self).edit_traits(*args, **kws)

    def configure_traits(self, *args, **kws):
        self._start_timer()
        return super(ModelView, self).configure_traits(*args, **kws)
Example #5
0
class ImagePlotUI(HasTraits):
    # container for all plots
    container = Instance(HPlotContainer)

    # Plot components within this container
    plot = Instance(CMapImagePlot)
    colorbar = Instance(ColorBar)

    # Plot data
    pd = Instance(ArrayPlotData)

    # View options
    colormap = Enum(colormaps)

    # Traits view definitions:
    traits_view = View(Group(
        UItem('container', editor=ComponentEditor(size=(350, 300)))),
                       resizable=True)

    plot_edit_view = View(Group(Item('colormap')), buttons=["OK", "Cancel"])

    #---------------------------------------------------------------------------
    # Private Traits
    #---------------------------------------------------------------------------

    _image_index = Instance(GridDataSource)
    _image_value = Instance(ImageData)

    _cmap = Trait(default_colormaps.gray, Callable)

    #---------------------------------------------------------------------------
    # Public View interface
    #---------------------------------------------------------------------------

    def __init__(self, *args, **kwargs):
        super(ImagePlotUI, self).__init__(*args, **kwargs)
        with errstate(invalid='ignore'):
            self.create_plot()

    def create_plot(self):

        # Create the mapper, etc
        self._image_index = GridDataSource(array([]),
                                           array([]),
                                           sort_order=("ascending",
                                                       "ascending"))
        image_index_range = DataRange2D(self._image_index)
        # self._image_index.on_trait_change(self._metadata_changed,
        #                                   "metadata_changed")

        self._image_value = ImageData(data=array([]), value_depth=1)
        image_value_range = DataRange1D(self._image_value)

        # Create the colormapped scalar plot
        self.plot = CMapImagePlot(
            index=self._image_index,
            index_mapper=GridMapper(range=image_index_range),
            value=self._image_value,
            value_mapper=self._cmap(image_value_range))

        # Add a left axis to the plot
        left = PlotAxis(orientation='left',
                        title="y",
                        mapper=self.plot.index_mapper._ymapper,
                        component=self.plot)
        self.plot.overlays.append(left)

        # Add a bottom axis to the plot
        bottom = PlotAxis(orientation='bottom',
                          title="x",
                          mapper=self.plot.index_mapper._xmapper,
                          component=self.plot)
        self.plot.overlays.append(bottom)

        # Add some tools to the plot
        self.plot.tools.append(PanTool(self.plot, constrain_key="shift"))
        self.plot.overlays.append(
            ZoomTool(component=self.plot, tool_mode="box", always_on=False))

        # Create a colorbar
        cbar_index_mapper = LinearMapper(range=image_value_range)
        self.colorbar = ColorBar(index_mapper=cbar_index_mapper,
                                 plot=self.plot,
                                 padding_top=self.plot.padding_top,
                                 padding_bottom=self.plot.padding_bottom,
                                 padding_right=40,
                                 resizable='v',
                                 width=10)

        # Create a container and add components
        self.container = HPlotContainer(padding=40,
                                        fill_padding=True,
                                        bgcolor="white",
                                        use_backbuffer=False)
        self.container.add(self.colorbar)
        self.container.add(self.plot)

    def update(self, image_data_source):
        xs = image_data_source.xs
        ys = image_data_source.ys
        zs = image_data_source.zs
        self.minz = zs.min()
        self.maxz = zs.max()
        self.colorbar.index_mapper.range.low = self.minz
        self.colorbar.index_mapper.range.high = self.maxz
        self._image_index.set_data(xs, ys)
        self._image_value.data = zs
        self.container.invalidate_draw()
        self.container.request_redraw()

    #---------------------------------------------------------------------------
    # Event handlers
    #---------------------------------------------------------------------------

    def _colormap_changed(self):
        self._cmap = default_colormaps.color_map_name_dict[self.colormap]
        if self.plot is not None:
            value_range = self.plot.color_mapper.range
            self.plot.color_mapper = self._cmap(value_range)
            self.container.request_redraw()
Example #6
0
class MonitorController(HasTraits):
    print_pool = List(Str)
    cpu_pool = List(Str)

    if g_enable_cpu_monitor:
        plot_cpu_temp = Instance(Plot)

    start_work = Button()
    end_work = Button()
    refresh_str = Button()
    refresh_call = Button()
    clear_pool = Button()
    suspend_all = Button()
    suspend_all_time = Button()
    kill_all = Button()
    resume_all = Button()

    manual_add = Button()
    manual_pid = Int

    def __init__(self):
        super(MonitorController, self).__init__()
        self.title = 'Process Monitor'
        run_task = dict()
        if g_enable_cpu_monitor:
            run_task.update({TaskEnum.E_WEEK_TASK: [self._cpu_change]})
            self._cpu_init()

        self.pMonitor = ProcessMonitorClass(self._add_print_pool, **run_task)

    def default_title(self):
        self.title = 'Process Monitor'

    def __do_cpu_temp_plot(self, temp):
        x = np.arange(0, len(self.deque_cpu))
        y = self.deque_cpu

        plot_data = ArrayPlotData(x=x, y=y)
        plot = Plot(plot_data)

        self.renderer = plot.plot(("x", "y"), color="blue")[0]
        plot.title = "cpu temperature: " + str(temp)
        self.plot_cpu_temp = plot

    def __do_cpu_inv(self):
        cpu_percent = CpuHelper.cpu_percent()
        self.cpu_pool = [
            'cpu  %d:  %f' % (cpu_index, percent)
            for cpu_index, percent in enumerate(cpu_percent)
        ]
        self.cpu_pool.insert(0, 'mean cpu:  %f' % (np.mean(cpu_percent)))

    def _cpu_change(self):
        temp, temp_str = CpuHelper.get_cpu_temp_proxy()
        self.deque_cpu.append(temp)
        self.__do_cpu_temp_plot(temp)

        self.__do_cpu_inv()

    def _cpu_init(self):
        temp, temp_str = CpuHelper.get_cpu_temp_proxy()
        self.deque_cpu = deque(maxlen=K_CPU_TEMP_CNT)
        self.deque_cpu.extend((np.ones(K_CPU_TEMP_CNT) * temp).tolist())
        self.__do_cpu_temp_plot(temp)

        self.__do_cpu_inv()

    def _start_work_fired(self):
        self.pMonitor.start_work()

    def _end_work_fired(self):
        self.pMonitor.end_work()

    def _refresh_str_fired(self):
        self.print_pool.append(str(self.pMonitor))

    def _refresh_call_fired(self):
        self.pMonitor()

    def _suspend_all_fired(self):
        self.pMonitor.rest_all(rest_time=True)

    def _suspend_all_time_fired(self):
        self.pMonitor.rest_all()

    def _resume_all_fired(self):
        self.pMonitor.awake_all()

    def _kill_all_fired(self):
        self.pMonitor.kill_all()

    def _clear_pool_fired(self):
        self.print_pool = []
        cmd_clear = 'cls' if platform.system().lower().find(
            "windows") >= 0 else 'clear'
        os.system(cmd_clear)

    def _manual_add_fired(self):
        self.pMonitor.manual_add_pid(self.manual_pid)

    def _add_print_pool(self, *args):
        self.print_pool.extend(args)

    view = View(
        Group(
            UItem('print_pool', editor=ListStrEditor(auto_add=False)),
            Item('start_work', label=u'监控开始', show_label=False),
            Item('end_work', label=u'监控结束', show_label=False),
            # Item('refresh_str', label=u'刷新str', show_label=False),
            Item('refresh_call', label=u'刷新call', show_label=False),
            Item('suspend_all', label=u'挂起所有', show_label=False),
            Item('suspend_all_time', label=u'挂起所有(定时失效)', show_label=False),
            Item('resume_all', label=u'恢复所有', show_label=False),
            Item('kill_all', label=u'杀死所有', show_label=False),
            Item('clear_pool', label=u'屏幕clear', show_label=False),
            Group(Item('manual_add', label=u'手动添加pid', show_label=False),
                  Item('manual_pid',
                       tooltip=u"输入pid后,按‘手动添加pid’",
                       width=360,
                       show_label=False),
                  orientation='horizontal',
                  show_border=True),
            label=u'控制处理',
            show_border=True)

        #  如果打开cpu监控g_enable_cpu_monitor且安装了chaco等
        #  打开下面代码onda的chaco会导致问题如果是conda环境就不要开了
        # ,
        # Group(
        #     Item('temp', label=u'cpu温度监控关闭,g_enable_cpu_monitor控制', show_label=False,
        #         width=500, height=320),
        #     label = u'信息显示',
        #     show_border = True,

        #     Item('plot_cpu_temp', editor=ComponentEditor() if g_enable_cpu_monitor
        #           else label=u'cpu温度监控关闭,g_enable_cpu_monitor控制', show_label=False,
        #         width=500, height=320),
        #     UItem('cpu_pool', editor=ListStrEditor(auto_add=False)),
        #     label = u'信息显示',
        #     show_border = True,
        # ),
        # resizable = True,
    )
Example #7
0
    def traits_view(self):
        cols = [
            CheckboxColumn(name='status'),
            ObjectColumn(name='status'),
            ObjectColumn(name='runid'),
            ObjectColumn(name='age'),
            ObjectColumn(name='age_err'),
            ObjectColumn(name='group'),
            ObjectColumn(name='aliquot'),
            ObjectColumn(name='sample'),
        ]

        gcols = [
            ObjectColumn(name='name'),
            ObjectColumn(
                name='weighted_mean',
                label='Wtd. Mean',
                format='%0.6f',
            ),
            ObjectColumn(name='weighted_mean_err',
                         format='%0.6f',
                         label=PLUSMINUS_ONE_SIGMA),
            ObjectColumn(name='mswd', format='%0.3f', label='MSWD'),
            ObjectColumn(name='displayn', label='N'),
            ObjectColumn(name='mean', format='%0.6f', label='Mean'),
            ObjectColumn(name='std', format='%0.6f', label='Std')
        ]

        button_grp = HGroup(UItem('save_button'), UItem('save_as_button'),
                            UItem('clear_button'),
                            UItem('open_via_finder_button'),
                            UItem('test_button')),

        repo_grp = VGroup(
            BorderVGroup(UItem('repo_filter'),
                         UItem('repositories',
                               width=200,
                               editor=ListStrEditor(selected='repository')),
                         label='Repositories'),
            BorderVGroup(UItem('name_filter'),
                         UItem('names', editor=ListStrEditor(selected='name')),
                         label='DataSets'))

        record_grp = VSplit(
            UItem(
                'records',
                editor=TableEditor(
                    columns=cols,
                    selected='selected',
                    sortable=False,
                    edit_on_first_click=False,
                    # clear_selection_on_dclicked=True,
                    menu=MenuManager(
                        Action(name='Group Selected',
                               perform=self._group_selected)),
                    selection_mode='rows')),
            UItem('groups', editor=TableEditor(columns=gcols)))

        main_grp = HSplit(repo_grp, record_grp)

        v = okcancel_view(
            VGroup(button_grp, main_grp),
            width=800,
            height=500,
            title='CSV Dataset',
            # handler=CSVDataSetFactoryHandler()
        )
        return v
Example #8
0
                raise ValueError("The selected port is already in use")
            self.error = False
        except ValueError, e:
            self.value = 0
            self.error = True
            self.error_msg = str(e)

    analog_input_view = View(
        VGroup(
            Item("id", label="Port-ID", style="custom"),
            Item("name", label="Name [Unit]"),
            Item("scale_factor"),
            Item("offset"),
            Item("value", style="readonly"),
            Group(
                UItem("error_msg", style="readonly"),
                visible_when="error",
                show_border=True,
                label="Error:",
                style_sheet="*{color:red}"
            ),
            label="Input-Port"
        ),
        resizable=True,
        buttons=[ConfirmButton, CancelButton],
        title="Add Input Port",
        width=300,
        height=200,
    )

Example #9
0
class PortAI(InputPort):
    """
    PortAI represents a analog input port. The class 
    provide a method to read the analog input of the port 
    and transform the value with the given scale-factor and the offset
    """

    scale_factor = Float

    offset = Float

    def __init__(self, board, port_id, scale_factor,
                 offset, name, edit_dialog=None):
        super(PortAI, self).__init__(board, port_id, name)
        if scale_factor == 0:
            raise ValueError("The scalefactor must unequal 0")
        self.scale_factor = scale_factor
        self.offset = offset
        self.edit_dialog = edit_dialog

    #=========================================================================
    # Methods to handle the port
    #=========================================================================

    def record_port(self, volt_interval=UL.BIP10VOLTS):
        """Reads the electrical voltage and transforms \
           the value with the scale factor and the offset.

        :param volt_interval: Interval of the electrical voltage of the machine
        :type volt_interval: int.
        :returns: The value of the machine
        :rtype: float
        """
        data = UL.cbAIn(self.board.id, self.id, volt_interval)
        volt = UL.cbToEngUnits(self.board.id, volt_interval, data)
        return self.scale_factor * volt + self.offset

    #=========================================================================
    # Methods to save and load the port
    #=========================================================================

    def save(self):
        """Returns the port as a dictionary for a JSON file

        :returns: Dictionary with all attributes of the port
        :rtype: Dictionary
        """
        return {"class_name": "PortAI", "name": self.name,
                "id": self.id, "input": self.is_input_port,
                "scale": self.scale_factor, "offset": self.offset}

    @staticmethod
    def load(args, card):
        """Creates a instance with the given attributes

        :param args: Attributes which are saved in the json-file
        :type args: Dictionary
        :param card: Measuring card of the experiment
        :type card: MeasuringCard
        :returns: Instance with the given attributes
        :rtype: PortAI
        """
        if card == None:
            edit_dialog = None
        else:
            edit_dialog = card.dialog_portai
        return PortAI(card, args["id"], args["scale"], args["offset"],
                      args["name"], edit_dialog)

    @staticmethod
    def generate_file(pid, name):
        return {"class_name": "PortAI", "name": name,
                "id": pid, "input": True, "scale": 1, "offset": 0}
    #=========================================================================
    # Traitsview + Traitsevent
    #=========================================================================

    edit_btn = Button("Edit Port")

    def _edit_btn_fired(self):
        # edit the port
        self.board.input_ports.remove(self)
        args = [self.id, self.scale_factor, self.offset, self.name]
        self.edit_dialog.update_attributes(args)
        if self.edit_dialog.open_dialog():
            self.board, self.id, self.scale_factor, \
                self.offset, self.name = self.edit_dialog._get_attributes()
        self.board.input_ports.append(self)

    traits_view = View(
        VGroup(
            Item("id", label="Port-ID", style="readonly"),
            Item("scale_factor", label="Scale", style="readonly"),
            Item("offset", style="readonly"),
            HGroup(
                spring,
                UItem("edit_btn")
            )
        ),
        resizable=True
    )
 def traits_view(self):
     v = View(
         UItem('canvas', editor=InstanceEditor(), style='custom',
               width=500))
     return v
 def traits_view(self):
     v = View(UItem('explanation', style='custom'))
     return v
Example #12
0
 def traits_view(self):
     v = View(
         HGroup(UItem('position', width=-60), UItem('detectors', width=250),
                UItem('counts', width=-60)))
     return v
Example #13
0
def get_view(style):
    return View(UItem("value", style=style), resizable=True)
Example #14
0
class Combobox(HasTraits):
    """Combobox in traits."""

    listeners = []

    values = Dict()

    selected_key = Str

    options = Property(Str, depends_on="values")

    def add_item(self, key, value):
        """Add a item in the dictionary and show it in the combobox

        :param key: Key which should show in the combobox
        :type key: string
        :param value: Belonging value
        :type value: object
        """
        self.values[key] = value
        if len(self.selected_key) < 1:
            self.selected_key = key

    def reset(self):
        """Resets all entries of the dictionary"""
        vals = deepcopy(self.values)
        for key in vals:
            if self.values.has_key(key):
                del self.values[key]
        self.selected_key = ""

    def show_value(self, value):
        """Shows the key of the given value

        :param value: Belonging value
        :type value: object
        """
        for key in self.values:
            if self.values[key] == value:
                self.selected_key = key

    def add_listener(self, listener):
        """
        Makes it possible that the parents can be notify 
        when the selected_key has changed.

        :param listener: Parent object
        :type listener: object
        """
        self.listeners.append(listener)

    def _selected_key_changed(self):
        # Notifies the listeners that the selected_key has changed.
        for listener in self.listeners:
            listener.selected_changed(self.selected_key)

    def _get_options(self):
        # Returns all keys
        return sorted(self.values.keys())

    def get_selected_value(self):
        # Returns the value of the selected key
        try:
            res = self.values[self.selected_key]
        except Exception:
            res = 'None'
        return res

    traits_view = View(
        UItem(name="selected_key",
              editor=CheckListEditor(name="options"),
              style_sheet='*{background-color:None}'), )
Example #15
0
 def traits_view(self):
     v = View(
         UItem('component', style='custom', editor=VideoComponentEditor()))
     return v
Example #16
0
class PortDO(OutputPort):
    """
    PortDO represents a digital output port. The class 
    provide a method to trigger a digital signal.
    """

    def __init__(self, board, port_id, name, edit_dialog):
        super(PortDO, self).__init__(board, port_id, name)
        self.edit_dialog = edit_dialog
        self.value = 0
        UL.cbDConfigPort(board.id, self.id, UL.DIGITALOUT)
        UL.cbDOut(self.board.id, self.id, self.value)

    #=========================================================================
    # Methods to handle the port
    #=========================================================================

    def trigger(self, reset_time=-1):
        """Triggers a digital signal.

        :param reset_time: Time (in seconds) to pass until reset the value. \
            If the reset_time will not set, the trigger will change \
            the electrical voltage.
        :type reset_time: float.
        :returns: True if the signal was sent, False otherwise.
        :rtype: bool
        :raises: ValueError, ctypes.ArgumentError
        """
        if reset_time < -1:
            raise ValueError("Invalid value: Value must positive")
        value = 0 if self.value == 255 else 255
        if reset_time != -1:
            UL.cbDOut(self.board.id, self.id, value)
            sleep(reset_time)
            UL.cbDOut(self.board.id, self.id, self.value)
        else:
            UL.cbDOut(self.board.id, self.id, value)
            self.value = value
        return True

    #=========================================================================
    # Methods to save and load the port
    #=========================================================================

    def save(self):
        """Returns the port as a dictionary for a JSON file

        :returns: Dictionary with all attributes of the port
        :rtype: Dictionary
        """
        return {"class_name": "PortDO", "name": self.name,
                "id": self.id, "input": self.is_input_port}

    @staticmethod
    def load(args, card):
        """Creates a instance with the given attributes

        :param args: Attributes which are saved in the json-file
        :type args: Dictionary
        :param card: Measuring card of the experiment
        :type card: MeasuringCard
        :returns: Instance with the loaded attributes
        :rtype: PortDO
        """
        edit_dialog = card.dialog_portdo
        return PortDO(card, args["id"], args["name"], edit_dialog)

    #=========================================================================
    # Traitsview + Traitsevent
    #=========================================================================

    edit_btn = Button("Edit Port")

    def _edit_btn_fired(self):
        # edit the port
        self.board.output_ports.remove(self)
        if self.edit_dialog.open_dialog():
            self.board, self.id, self.name = self.edit_dialog._get_attributes()
        self.board.output_ports.append(self)

    traits_view = View(
        VGroup(
            Item("id", label="Port-ID", style="readonly"),
            Item("name", style="readonly"),
            HGroup(
                spring,
                UItem("edit_btn")
            )
        ),
        resizable=True
    )
Example #17
0
 def traits_view(self):
     return View(UItem('path'))
Example #18
0
class Demo(HasTraits):

    list1 = List(Int)

    list2 = List(Float)

    list3 = List(Str, maxlen=3)

    list4 = List(Enum('red', 'green', 'blue', 2, 3))

    list5 = List(Range(low=0.0, high=10.0))

    # 'low' and 'high' are used to demonstrate lists containing dynamic ranges.
    low = Float(0.0)
    high = Float(1.0)

    list6 = List(Range(low=-1.0, high='high'))

    list7 = List(Range(low='low', high='high'))

    pop1 = Button("Pop from first list")

    sort1 = Button("Sort first list")

    # This will be str(self.list1).
    list1str = Property(Str, depends_on='list1')

    traits_view = \
        View(
            HGroup(
                # This VGroup forms the column of CSVListEditor examples.
                VGroup(
                    Item('list1', label="List(Int)",
                         editor=CSVListEditor(ignore_trailing_sep=False),
                         tooltip='options: ignore_trailing_sep=False'),
                    Item('list1', label="List(Int)", style='readonly',
                         editor=CSVListEditor()),
                    Item('list2', label="List(Float)",
                         editor=CSVListEditor(enter_set=True, auto_set=False),
                         tooltip='options: enter_set=True, auto_set=False'),
                    Item('list3', label="List(Str, maxlen=3)",
                         editor=CSVListEditor()),
                    Item('list4',
                         label="List(Enum('red', 'green', 'blue', 2, 3))",
                         editor=CSVListEditor(sep=None),
                         tooltip='options: sep=None'),
                    Item('list5', label="List(Range(low=0.0, high=10.0))",
                         editor=CSVListEditor()),
                    Item('list6', label="List(Range(low=-1.0, high='high'))",
                         editor=CSVListEditor()),
                    Item('list7', label="List(Range(low='low', high='high'))",
                         editor=CSVListEditor()),
                    springy=True,
                ),
                # This VGroup forms the right column; it will display the
                # Python str representation of the lists.
                VGroup(
                    UItem('list1str', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list1str', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list2', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list3', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list4', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list5', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list6', editor=TextEditor(),
                          enabled_when='False', width=240),
                    UItem('list7', editor=TextEditor(),
                          enabled_when='False', width=240),
                ),
            ),
            '_',
            HGroup('low', 'high', spring, UItem('pop1'), UItem('sort1')),
            Heading("Notes"),
            Label("Hover over a list to see which editor options are set, "
                  "if any."),
            Label("The editor of the first list, List(Int), uses "
                  "ignore_trailing_sep=False, so a trailing comma is "
                  "an error."),
            Label("The second list is a read-only view of the first list."),
            Label("The editor of the List(Float) example has enter_set=True "
                  "and auto_set=False; press Enter to validate."),
            Label("The List(Str) example will accept at most 3 elements."),
            Label("The editor of the List(Enum(...)) example uses sep=None, "
                  "i.e. whitespace acts as a separator."),
            Label("The last two List(Range(...)) examples take one or both "
                  "of their limits from the Low and High fields below."),
            width=720,
            title="CSVListEditor Demonstration",
        )

    def _list1_default(self):
        return [1, 4, 0, 10]

    def _get_list1str(self):
        return str(self.list1)

    def _pop1_fired(self):
        if len(self.list1) > 0:
            x = self.list1.pop()
            print(x)

    def _sort1_fired(self):
        self.list1.sort()
Example #19
0
 def graph_view(self):
     v = View(UItem('graph', style='custom'),
              handler=self.handler_klass,
              title=self.name)
     return v
Example #20
0
def edit_task_extensions(ts):
    e = EditExtensionsView()
    for args in ts:
        e.add_additions(*args)
    e.load()

    nodes = [
        TreeNode(node_for=[ViewModel],
                 icon_open='',
                 children='task_extensions'),
        TETreeNode(node_for=[TaskExtensionModel],
                   auto_open=False,
                   children='additions',
                   label='name',
                   menu=MenuManager(
                       Action(name='Enable All',
                              visible_when='not object.all_enabled',
                              action='set_all_enabled'),
                       Action(name='Disable All',
                              visible_when='object.all_enabled',
                              action='set_all_disabled'))),
        AdditionTreeNode(node_for=[AdditionModel],
                         label='name',
                         menu=MenuManager(
                             Action(name='Enable',
                                    action='set_enabled',
                                    visible_when='not object.enabled'),
                             Action(name='Disable',
                                    visible_when='object.enabled',
                                    action='set_disabled')))
    ]
    tgrp = VGroup(
        UItem('predefined', tooltip='List of Predefined UI configurations'),
        UItem(
            'filter_value',
            tooltip=
            'Filter items by name. Show only items where NAME starts with the specified value'
        ),
        HGroup(
            icon_button_editor('collapse_all', 'collapse'),
            icon_button_editor('expand_all', 'collapse'),
        ),
        UItem(
            'view_model',
            height=-400,
            editor=TreeEditor(
                nodes=nodes,
                # selection_mode='extended',
                hide_root=True,
                selected='selected',
                dclick='dclicked',
                show_disabled=True,
                collapse_all='collapse_all',
                expand_all='expand_all',
                refresh='refresh_needed',
                refresh_all_icons='refresh_all_needed',
                editable=False)))
    dgrp = VGroup(
        UItem(
            'description',
            style='custom',
            # height=-100,
            editor=TextEditor(read_only=True)),
        show_border=True,
        label='Description')

    av = View(VGroup(tgrp, dgrp),
              title='Edit UI',
              width=500,
              height=700,
              resizable=True,
              handler=EEHandler(),
              buttons=['OK', 'Cancel'],
              kind='livemodal')

    # info = e.configure_traits(view=AView)
    info = e.edit_traits(view=av)
    if info.result:
        e.dump()
        return confirm(None, 'Restart?') == YES
Example #21
0
class PlotUI(HasTraits):

    # container for all plots
    container = Instance(HPlotContainer)

    # Plot components within this container:
    polyplot = Instance(ContourPolyPlot)
    lineplot = Instance(ContourLinePlot)
    cross_plot = Instance(Plot)
    cross_plot2 = Instance(Plot)
    colorbar = Instance(ColorBar)

    # plot data
    pd = Instance(ArrayPlotData)

    # view options
    num_levels = Int(15)
    colormap = Enum(colormaps)

    #Traits view definitions:
    traits_view = View(Group(
        UItem('container', editor=ComponentEditor(size=(800, 600)))),
                       resizable=True)

    plot_edit_view = View(Group(Item('num_levels'), Item('colormap')),
                          buttons=["OK", "Cancel"])

    #---------------------------------------------------------------------------
    # Private Traits
    #---------------------------------------------------------------------------

    _image_index = Instance(GridDataSource)
    _image_value = Instance(ImageData)

    _cmap = Trait(default_colormaps.jet, Callable)

    #---------------------------------------------------------------------------
    # Public View interface
    #---------------------------------------------------------------------------

    def __init__(self, *args, **kwargs):
        super(PlotUI, self).__init__(*args, **kwargs)
        # FIXME: 'with' wrapping is temporary fix for infinite range in initial
        # color map, which can cause a distracting warning print. This 'with'
        # wrapping should be unnecessary after fix in color_mapper.py.
        with errstate(invalid='ignore'):
            self.create_plot()

    def create_plot(self):

        # Create the mapper, etc
        self._image_index = GridDataSource(array([]),
                                           array([]),
                                           sort_order=("ascending",
                                                       "ascending"))
        image_index_range = DataRange2D(self._image_index)
        self._image_index.on_trait_change(self._metadata_changed,
                                          "metadata_changed")

        self._image_value = ImageData(data=array([]), value_depth=1)
        image_value_range = DataRange1D(self._image_value)

        # Create the contour plots
        self.polyplot = ContourPolyPlot(index=self._image_index,
                                        value=self._image_value,
                                        index_mapper=GridMapper(range=
                                            image_index_range),
                                        color_mapper=\
                                            self._cmap(image_value_range),
                                        levels=self.num_levels)

        self.lineplot = ContourLinePlot(
            index=self._image_index,
            value=self._image_value,
            index_mapper=GridMapper(range=self.polyplot.index_mapper.range),
            levels=self.num_levels)

        # Add a left axis to the plot
        left = PlotAxis(orientation='left',
                        title="y",
                        mapper=self.polyplot.index_mapper._ymapper,
                        component=self.polyplot)
        self.polyplot.overlays.append(left)

        # Add a bottom axis to the plot
        bottom = PlotAxis(orientation='bottom',
                          title="x",
                          mapper=self.polyplot.index_mapper._xmapper,
                          component=self.polyplot)
        self.polyplot.overlays.append(bottom)

        # Add some tools to the plot
        self.polyplot.tools.append(
            PanTool(self.polyplot, constrain_key="shift"))
        self.polyplot.overlays.append(
            ZoomTool(component=self.polyplot, tool_mode="box",
                     always_on=False))
        self.polyplot.overlays.append(
            LineInspector(component=self.polyplot,
                          axis='index_x',
                          inspect_mode="indexed",
                          write_metadata=True,
                          is_listener=True,
                          color="white"))
        self.polyplot.overlays.append(
            LineInspector(component=self.polyplot,
                          axis='index_y',
                          inspect_mode="indexed",
                          write_metadata=True,
                          color="white",
                          is_listener=True))

        # Add these two plots to one container
        contour_container = OverlayPlotContainer(padding=20,
                                                 use_backbuffer=True,
                                                 unified_draw=True)
        contour_container.add(self.polyplot)
        contour_container.add(self.lineplot)

        # Create a colorbar
        cbar_index_mapper = LinearMapper(range=image_value_range)
        self.colorbar = ColorBar(index_mapper=cbar_index_mapper,
                                 plot=self.polyplot,
                                 padding_top=self.polyplot.padding_top,
                                 padding_bottom=self.polyplot.padding_bottom,
                                 padding_right=40,
                                 resizable='v',
                                 width=30)

        self.pd = ArrayPlotData(line_index=array([]),
                                line_value=array([]),
                                scatter_index=array([]),
                                scatter_value=array([]),
                                scatter_color=array([]))

        self.cross_plot = Plot(self.pd, resizable="h")
        self.cross_plot.height = 100
        self.cross_plot.padding = 20
        self.cross_plot.plot(("line_index", "line_value"), line_style="dot")
        self.cross_plot.plot(
            ("scatter_index", "scatter_value", "scatter_color"),
            type="cmap_scatter",
            name="dot",
            color_mapper=self._cmap(image_value_range),
            marker="circle",
            marker_size=8)

        self.cross_plot.index_range = self.polyplot.index_range.x_range

        self.pd.set_data("line_index2", array([]))
        self.pd.set_data("line_value2", array([]))
        self.pd.set_data("scatter_index2", array([]))
        self.pd.set_data("scatter_value2", array([]))
        self.pd.set_data("scatter_color2", array([]))

        self.cross_plot2 = Plot(self.pd,
                                width=140,
                                orientation="v",
                                resizable="v",
                                padding=20,
                                padding_bottom=160)
        self.cross_plot2.plot(("line_index2", "line_value2"), line_style="dot")
        self.cross_plot2.plot(
            ("scatter_index2", "scatter_value2", "scatter_color2"),
            type="cmap_scatter",
            name="dot",
            color_mapper=self._cmap(image_value_range),
            marker="circle",
            marker_size=8)

        self.cross_plot2.index_range = self.polyplot.index_range.y_range

        # Create a container and add components
        self.container = HPlotContainer(padding=40,
                                        fill_padding=True,
                                        bgcolor="white",
                                        use_backbuffer=False)
        inner_cont = VPlotContainer(padding=0, use_backbuffer=True)
        inner_cont.add(self.cross_plot)
        inner_cont.add(contour_container)
        self.container.add(self.colorbar)
        self.container.add(inner_cont)
        self.container.add(self.cross_plot2)

    def update(self, model):
        self.minz = model.minz
        self.maxz = model.maxz
        self.colorbar.index_mapper.range.low = self.minz
        self.colorbar.index_mapper.range.high = self.maxz
        self._image_index.set_data(model.xs, model.ys)
        self._image_value.data = model.zs
        self.pd.update_data(line_index=model.xs, line_index2=model.ys)
        self.container.invalidate_draw()
        self.container.request_redraw()

    #---------------------------------------------------------------------------
    # Event handlers
    #---------------------------------------------------------------------------

    def _metadata_changed(self, old, new):
        """ This function takes out a cross section from the image data, based
        on the line inspector selections, and updates the line and scatter
        plots."""

        self.cross_plot.value_range.low = self.minz
        self.cross_plot.value_range.high = self.maxz
        self.cross_plot2.value_range.low = self.minz
        self.cross_plot2.value_range.high = self.maxz
        if "selections" in self._image_index.metadata:
            x_ndx, y_ndx = self._image_index.metadata["selections"]
            if y_ndx and x_ndx:
                xdata, ydata = self._image_index.get_data()
                xdata, ydata = xdata.get_data(), ydata.get_data()
                self.pd.update_data(
                    line_value=self._image_value.data[y_ndx, :],
                    line_value2=self._image_value.data[:, x_ndx],
                    scatter_index=array([xdata[x_ndx]]),
                    scatter_index2=array([ydata[y_ndx]]),
                    scatter_value=array([self._image_value.data[y_ndx,
                                                                x_ndx]]),
                    scatter_value2=array(
                        [self._image_value.data[y_ndx, x_ndx]]),
                    scatter_color=array([self._image_value.data[y_ndx,
                                                                x_ndx]]),
                    scatter_color2=array(
                        [self._image_value.data[y_ndx, x_ndx]]))
        else:
            self.pd.update_data({
                "scatter_value": array([]),
                "scatter_value2": array([]),
                "line_value": array([]),
                "line_value2": array([])
            })

    def _colormap_changed(self):
        self._cmap = default_colormaps.color_map_name_dict[self.colormap]
        if self.polyplot is not None:
            value_range = self.polyplot.color_mapper.range
            self.polyplot.color_mapper = self._cmap(value_range)
            value_range = self.cross_plot.color_mapper.range
            self.cross_plot.color_mapper = self._cmap(value_range)
            # FIXME: change when we decide how best to update plots using
            # the shared colormap in plot object
            self.cross_plot.plots["dot"][0].color_mapper = self._cmap(
                value_range)
            self.cross_plot2.plots["dot"][0].color_mapper = self._cmap(
                value_range)
            self.container.request_redraw()

    def _num_levels_changed(self):
        if self.num_levels > 3:
            self.polyplot.levels = self.num_levels
            self.lineplot.levels = self.num_levels
Example #22
0
    def _get_groups(self):
        xgrp = VGroup(
            Item('index_attr',
                 editor=EnumEditor(
                     values={
                         'uage': '01:Age',
                         'uF': '02:Ar40*/Ar39k',
                         'Ar40/Ar36': '03:Ar40/Ar36',
                         'Ar40/Ar39': '04:Ar40/Ar39',
                         'Ar40/Ar38': '05:Ar40/Ar38',
                         'Ar39/Ar37': '06:Ar39/Ar37',
                         'uAr40/Ar36': '07:uncor. Ar40/Ar36',
                         'Ar40': '08:Ar40',
                         'Ar39': '09:Ar39',
                         'Ar38': '10:Ar38',
                         'Ar37': '11:Ar37',
                         'Ar36': '12:Ar36',
                     }),
                 label='X Value'),
            HGroup(UItem('use_static_limits'),
                   Item('xlow',
                        label='Min.',
                        enabled_when='object.use_static_limits'),
                   Item('xhigh',
                        label='Max.',
                        enabled_when='object.use_static_limits'),
                   show_border=True,
                   label='Static Limits'),
            HGroup(
                UItem('use_asymptotic_limits'),
                Item(
                    'asymptotic_width',
                    label='% Width',
                    tooltip=
                    'Width of asymptotic section that is less than the Asymptotic %'
                ),
                Item('asymptotic_percent',
                     tooltip='Percent of Max probability',
                     label='% Height'),
                icon_button_editor(
                    'refresh_asymptotic_button',
                    'refresh',
                    enabled_when='object.use_asymptotic_limits',
                    tooltip='Refresh plot with defined asymptotic limits'),
                enabled_when=
                'not object.use_centered_range and not object.use_static_limits',
                show_border=True,
                label='Asymptotic Limits'),
            HGroup(UItem('use_centered_range'),
                   UItem('centered_range',
                         enabled_when='object.use_centered_range'),
                   label='Center on fixed range',
                   show_border=True,
                   enabled_when='not object.use_static_limits'))

        grp_grp = VGroup(UItem('group',
                               style='custom',
                               editor=InstanceEditor(view='simple_view')),
                         show_border=True,
                         label='Group Attributes')

        g = Group(Item('probability_curve_kind',
                       width=-150,
                       label='Probability Curve Method'),
                  Item('mean_calculation_kind',
                       width=-150,
                       label='Mean Calculation Method'),
                  Item('error_calc_method',
                       width=-150,
                       label='Error Calculation Method'),
                  Item('nsigma', label='Age Error NSigma'),
                  HGroup(Item('include_j_error', label='Include in Analyses'),
                         Item('include_j_error_in_mean',
                              label='Include in Mean',
                              enabled_when='not include_j_error'),
                         show_border=True,
                         label='J Error'),
                  Item('include_irradiation_error'),
                  Item('include_decay_error'),
                  show_border=True,
                  label='Calculations')

        g2 = Group(
            VGroup(HGroup(
                Item('display_mean_indicator', label='Indicator'),
                Item('display_mean',
                     label='Value',
                     enabled_when='display_mean_indicator'),
                Item('display_percent_error',
                     label='%Error',
                     enabled_when='display_mean_indicator')),
                   HGroup(Item('mean_sig_figs', label='Mean'),
                          show_border=True,
                          label='SigFigs'),
                   show_border=True,
                   label='Mean'),
            VGroup(Item('display_inset'),
                   Item('inset_location'),
                   HGroup(Item('inset_width', label='Width'),
                          Item('inset_height', label='Height')),
                   show_border=True,
                   label='Inset'),
            Item('label_box'),
            Item('analysis_number_sorting', label='Analysis# Sort'),
            Item('use_cmap_analysis_number'),
            Item('cmap_analysis_number'),
            Item('use_latest_overlay'),
            HGroup(
                Item('analysis_label_display', width=100, style='readonly'),
                icon_button_editor('edit_label_format',
                                   'cog',
                                   tooltip='Open Label maker')),
            HGroup(Item('show_info', label='Show'),
                   Item('show_mean_info',
                        label='Mean',
                        enabled_when='show_info'),
                   Item('show_error_type_info',
                        label='Error Type',
                        enabled_when='show_info'),
                   show_border=True,
                   label='Info'),
            # VGroup(UItem('fill_group', style='custom',
            #              editor=InstanceEditor(view='simple_view')),
            #        HGroup(icon_button_editor('edit_group_fill_color_button', 'cog'), spring),
            #        show_border=True, label='Fill'),
            # VGroup(HGroup(UItem('use_filled_line'),
            #               Item('fill_color', enabled_when='use_filled_line')),
            #        Item('fill_alpha'),
            #        icon_button_editor('edit_group_fill_color_button', 'cog'),
            #        label='Fill',
            #        show_border=True),
            show_border=True,
            label='Display')

        egrp = VGroup(HGroup(
            Item('x_end_caps', label='X'),
            Item('y_end_caps', label='Y'),
            label='End Caps',
        ),
                      Item('error_bar_nsigma', label='NSigma'),
                      show_border=True,
                      label='Error Bars')
        main_grp = VGroup(self._get_title_group(), xgrp, grp_grp, g, g2, egrp)

        orgp = Group(
            main_grp,
            # label_grp,
            # layout='tabbed',
            label='Options')

        # axis_grp = VGroup(self._get_x_axis_group(),
        #                   self._get_y_axis_group(),
        #                   label='Axes')
        #
        # label_grp = VGroup(self._get_indicator_font_group(),
        #                    self._get_label_font_group(),
        #                    label='Fonts')
        return orgp,  # axis_grp, label_grp
Example #23
0
        """
        _, ext = splitext(filename)
        file_factory = self._file_factory[ext]
        demo_file = file_factory(parent=self, name=filename)
        return demo_file


# -------------------------------------------------------------------------
#  Defines the demo tree editor:
# -------------------------------------------------------------------------

demo_path_view = View(
    UItem(
        "description",
        style="readonly",
        editor=HTMLEditor(
            format_text=True,
            base_url_name='base_url',
        ),
    ),
    id="demo_path_view",
    kind='subpanel',
)

demo_file_view = View(
    HSplit(
        UItem(
            "description",
            style="readonly",
            editor=HTMLEditor(
                format_text=True,
                base_url_name='base_url',
Example #24
0
 def traits_view(self):
     v = View(VGroup(UItem('conn_spec', style='custom'),
                     UItem('_'),
                     CustomLabel('connection_status',
                                 color_name='connection_color')))
     return v
Example #25
0
        self.experiment.create_reference_image()
        f = get_all_files(resized_images_dir)[0]
        self.experiment.recorder.update_reference(f)
        self.loaded_reference = True

    def _edit_roi_btn_fired(self):
        self.roi_selector.open_dialog()
        f = get_all_files(resized_images_dir)[0]
        self.experiment.recorder.update_reference(f)

    def _correlate_btn_fired(self):
        self.correlation_method.correlate_all_images()

    view = View(
        VGroup(VGroup(Item("subset_size", label="Subset size [pixel]"),
                      Item("reference_btn",
                           label="Set reference Image:",
                           enabled_when='record_mode'),
                      Item("edit_roi_btn",
                           label="Define region of interest",
                           enabled_when="loaded_reference"),
                      label='General'),
               VGroup(UItem('unit_converter', style='custom'),
                      enabled_when="loaded_reference"),
               VGroup(
                   UItem("correlation_method",
                         style="custom",
                         enabled_when="loaded_reference"),
                   UItem("correlate_btn", enabled_when="loaded_reference")),
               layout='normal'))
Example #26
0
class SbpRelayView(HasTraits):
    """
    SBP Relay view- Class allows user to specify port, IP address, and message set
    to relay over UDP and to configure a http connection
    """
    running = Bool(False)
    configured = Bool(False)
    broadcasting = Bool(False)
    msg_enum = Enum('Observations', 'All')
    ip_ad = String(DEFAULT_UDP_ADDRESS)
    port = Int(DEFAULT_UDP_PORT)
    information = String(
        'UDP Streaming\n\nBroadcast SBP information received by'
        ' the console to other machines or processes over UDP. With the \'Observations\''
        ' radio button selected, the console will broadcast the necessary information'
        ' for a rover Piksi to acheive an RTK solution.'
        '\n\nThis can be used to stream observations to a remote Piksi through'
        ' aircraft telemetry via ground control software such as MAVProxy or'
        ' Mission Planner.')
    show_networking = Bool(False)
    http_information = String(
        'Experimental Piksi Networking\n\n'
        "Use this widget to connect Piksi receivers to http servers.\n\n")
    start = Button(label='Start', toggle=True, width=32)
    stop = Button(label='Stop', toggle=True, width=32)
    connected_rover = Bool(False)
    connect_rover = Button(label='Connect', toggle=True, width=32)
    disconnect_rover = Button(label='Disconnect', toggle=True, width=32)
    url = String()
    base_pragma = String()
    rover_pragma = String()
    base_device_uid = String()
    rover_device_uid = String()
    toggle = True
    view = View(
        VGroup(
            spring,
            HGroup(
                VGroup(
                    Item('running',
                         show_label=True,
                         style='readonly',
                         visible_when='running'),
                    Item('msg_enum',
                         label="Messages to broadcast",
                         style='custom',
                         enabled_when='not running'),
                    Item('ip_ad',
                         label='IP Address',
                         enabled_when='not running'),
                    Item('port', label="Port", enabled_when='not running'),
                    HGroup(
                        spring,
                        UItem('start',
                              enabled_when='not running',
                              show_label=False),
                        UItem('stop', enabled_when='running',
                              show_label=False), spring)),
                VGroup(
                    Item('information',
                         label="Notes",
                         height=10,
                         editor=MultilineTextEditor(
                             TextEditor(multi_line=True)),
                         style='readonly',
                         show_label=False,
                         resizable=True,
                         padding=15),
                    spring,
                ),
            ), spring,
            HGroup(
                VGroup(
                    HGroup(
                        spring,
                        UItem('connect_rover',
                              enabled_when='not connected_rover',
                              show_label=False),
                        UItem('disconnect_rover',
                              enabled_when='connected_rover',
                              show_label=False), spring),
                    HGroup(
                        Spring(springy=False, width=2),
                        Item('url',
                             enabled_when='not connected_rover',
                             show_label=True), Spring(springy=False, width=2)),
                    HGroup(spring, Item('base_pragma', label='Base option '),
                           Item('base_device_uid', label='Base device '),
                           spring),
                    HGroup(spring, Item('rover_pragma', label='Rover option'),
                           Item('rover_device_uid', label='Rover device'),
                           spring),
                ),
                VGroup(
                    Item('http_information',
                         label="Notes",
                         height=10,
                         editor=MultilineTextEditor(
                             TextEditor(multi_line=True)),
                         style='readonly',
                         show_label=False,
                         resizable=True,
                         padding=15),
                    spring,
                ),
                visible_when='show_networking',
            ), spring))

    def __init__(self,
                 link,
                 show_networking=False,
                 device_uid=None,
                 url='',
                 whitelist=None,
                 rover_pragma='',
                 base_pragma='',
                 rover_uuid='',
                 base_uuid='',
                 connect=False,
                 verbose=False):
        """
        Traits tab with UI for UDP broadcast of SBP.

        Parameters
        ----------
        link : sbp.client.handler.Handler
          Link for SBP transfer to/from Piksi.
        device_uid : str
          Piksi Device UUID (defaults to None)
        base : str
          HTTP endpoint
        whitelist : [int] | None
          Piksi Device UUID (defaults to None)

        """
        self.link = link
        # Whitelist used for UDP broadcast view
        self.msgs = OBS_MSGS
        # register a callback when the msg_enum trait changes
        self.on_trait_change(self.update_msgs, 'msg_enum')
        # Whitelist used for broadcasting
        self.whitelist = whitelist
        self.device_uid = None
        self.python_console_cmds = {'update': self}
        self.rover_pragma = rover_pragma
        self.base_pragma = base_pragma
        self.rover_device_uid = rover_uuid
        self.base_device_uid = base_uuid
        self.verbose = verbose
        self.http_watchdog_thread = None
        self.url = url
        self.show_networking = show_networking
        if connect:
            self.connect_when_uuid_received = True
        else:
            self.connect_when_uuid_received = False

    def update_msgs(self):
        """Updates the instance variable msgs which store the msgs that we
        will send over UDP.

        """
        if self.msg_enum == 'Observations':
            self.msgs = OBS_MSGS
        elif self.msg_enum == 'All':
            self.msgs = [None]
        else:
            raise NotImplementedError

    def set_route(self, uuid=None, serial_id=None, channel=CHANNEL_UUID):
        """Sets serial_id hash for HTTP headers.

        Parameters
        ----------
        uuid: str
          real uuid of device
        serial_id : int
          Piksi device ID
        channel : str
          UUID namespace for device UUID

        """
        if uuid:
            device_uid = uuid
        elif serial_id:
            device_uid = str(get_uuid(channel, serial_id % 1000))
        else:
            print(
                "Improper call of set_route, either a serial number or UUID should be passed"
            )
            device_uid = str(get_uuid(channel, 1234))
            print("Setting UUID to default value of {0}".format(device_uid))
        self.device_uid = device_uid

    def _prompt_setting_error(self, text):
        """Nonblocking prompt for a device setting error.

        Parameters
        ----------
        text : str
          Helpful error message for the user

        """
        prompt = CallbackPrompt(title="Setting Error", actions=[close_button])
        prompt.text = text
        prompt.run(block=False)

    def _disconnect_rover_fired(self):
        """Handle callback for HTTP rover disconnects.

        """
        try:
            if isinstance(self.http_watchdog_thread, threading.Thread) and \
               not self.http_watchdog_thread.stopped():
                self.http_watchdog_thread.stop()
            else:
                print(("Unable to disconnect: Http watchdog thread "
                       "inititalized at {0} and connected since {1} has "
                       "already been stopped").format(
                           self.http_watchdog_thread.get_init_time(),
                           self.http_watchdog_thread.get_connect_time()))
            self.connected_rover = False
        except:
            self.connected_rover = False
            import traceback
            print(traceback.format_exc())

    def _connect_rover_fired(self):
        """Handle callback for HTTP rover connections.  Launches an instance of http_watchdog_thread.
        """
        if not self.device_uid:
            msg = "\nDevice ID not found!\n\nConnection requires a valid Piksi device ID."
            self._prompt_setting_error(msg)
            return
        try:
            _base_device_uid = self.base_device_uid or self.device_uid
            _rover_device_uid = self.rover_device_uid or self.device_uid
            config = HttpConsoleConnectConfig(self.link, self.device_uid,
                                              self.url, self.whitelist,
                                              self.rover_pragma,
                                              self.base_pragma,
                                              _rover_device_uid,
                                              _base_device_uid)
            self.http_watchdog_thread = HttpWatchdogThread(
                link=self.link,
                http_config=config,
                stopped_callback=self._disconnect_rover_fired,
                verbose=self.verbose)
            self.connected_rover = True
            self.http_watchdog_thread.start()
        except:
            if isinstance(self.http_watchdog_thread, threading.Thread) \
               and self.http_watchdog_thread.stopped():
                self.http_watchdog_thread.stop()
            self.connected_rover = False
            import traceback
            print(traceback.format_exc())

    def _start_fired(self):
        """Handle start udp broadcast button. Registers callbacks on
        self.link for each of the self.msgs If self.msgs is None, it
        registers one generic callback for all messages.

        """
        self.running = True
        try:
            self.func = UdpLogger(self.ip_ad, self.port)
            self.link.add_callback(self.func, self.msgs)
        except:
            import traceback
            print(traceback.format_exc())

    def _stop_fired(self):
        """Handle the stop udp broadcast button. It uses the self.funcs and
        self.msgs to remove the callbacks that were registered when the
        start button was pressed.

        """
        try:
            self.link.remove_callback(self.func, self.msgs)
            self.func.__exit__()
            self.func = None
            self.running = False
        except:
            import traceback
            print(traceback.format_exc())
Example #27
0
 def traits_view(self):
     v = View(UItem('finder', style='custom'))
     return v
Example #28
0
 def traits_view(self):
     v = View(UItem('main_view', style='custom'))
     return v
class InterruptibleTaskExample(HasStrictTraits):
    #: The executor to submit tasks to.
    traits_executor = Instance(TraitsExecutor)

    #: The future object returned on task submission.
    future = Instance(IterationFuture)

    #: Number of points to use.
    sample_count = Int(10**8)

    #: Message about state of calculation.
    message = Str("No previous calculation runs")

    #: Button to calculate, plus its enabled state.
    calculate = Button()
    can_calculate = Property(Bool(), observe="future")

    #: Button to cancel, plus its enabled state.
    cancel = Button()
    can_cancel = Property(Bool(), observe="future.cancellable")

    @observe("calculate")
    def _submit_calculation(self, event):
        self.message = "Calculating π"
        self.future = submit_iteration(self.traits_executor, approximate_pi,
                                       self.sample_count)

    @observe("cancel")
    def _request_cancellation(self, event):
        self.future.cancel()
        self.message = "Cancelling"

    @observe("future:done")
    def _report_result(self, event):
        if self.future.state == CANCELLED:
            self.message = "Cancelled"
        elif self.future.state == FAILED:
            self.message = f"Unexpected error: {self.future.exception[1]}"
        elif self.future.state == COMPLETED:
            self.message = f"Complete: π ≈ {self.future.result:.6f}"
        else:
            # Shouldn't ever get here: CANCELLED, FAILED and COMPLETED
            # are the only possible final states of a future.
            assert False, f"Impossible state: {self.future.state}"
        self.future = None

    @observe("future:result_event")
    def _report_partial_result(self, event):
        self.message = f"Running: π ≈ {event.new:.6f}"

    def _get_can_calculate(self):
        return self.future is None

    def _get_can_cancel(self):
        return self.future is not None and self.future.cancellable

    traits_view = View(
        Item("sample_count"),
        UItem("message", style="readonly"),
        HGroup(
            UItem("calculate", enabled_when="can_calculate"),
            UItem("cancel", enabled_when="can_cancel"),
        ),
        resizable=True,
    )
Example #30
0
 def traits_view(self):
     v = View(
         BorderVGroup(UItem('results',
                            editor=TabularEditor(adapter=self.adapter)),
                      label='T-test Probabilities'))
     return v