Example #1
0
    def create_downloading_item(self, downloading_dict):
        book_name = downloading_dict['file_name']
        item_widget = QWidget()
        item_widget.setObjectName(f'{downloading_dict["id"]}')
        hbox_layout = QHBoxLayout()

        item_label = QLabel()
        item_label.setPixmap(QPixmap(os.path.join(assets_path, 'book.png')))
        hbox_layout.addWidget(item_label)

        vlayout = QVBoxLayout()
        file_name_label = QLabel(book_name)
        download_progress = ProgressBar(
            minimum=0, maximum=100, textVisible=False, objectName=f'{downloading_dict["id"]}_progress_bar')
        style_sheet = f'''
            #{downloading_dict["id"]}_progress_bar {{
                min-height: 6px;
                max-height: 6px;
                border-radius: 6px;
            }}
            #{downloading_dict["id"]}_progress_bar::chunk {{
                border-radius: 6px;
                width:12px;
                background-color: #D20A0A;
            }}        
        '''
        download_progress.setStyleSheet(style_sheet)
        vlayout.addWidget(file_name_label)
        vlayout.addWidget(download_progress)

        h_in_v_item_layout = QHBoxLayout()
        h_in_v_item_layout.addWidget(
            QLabel(downloading_dict['size']), Qt.AlignLeft)

        percent_label = QLabel()
        percent_label.setObjectName(f'{downloading_dict["id"]}_percent')
        percent_label.setText(f'已经下载:0%')
        h_in_v_item_layout.addWidget(percent_label, Qt.AlignHCenter)

        speed_label = QLabel()
        speed_label.setObjectName(f'{downloading_dict["id"]}_speed')
        speed_label.setText("0 kb/s")
        h_in_v_item_layout.addWidget(speed_label, Qt.AlignRight)

        vlayout.addLayout(h_in_v_item_layout)
        hbox_layout.addLayout(vlayout)

        del_btn = QPushButton()
        del_btn.setIcon(QIcon(os.path.join(assets_path, 'delete.png')))
        del_btn.setStyleSheet("QPushButton{border:none}")
        del_btn.clicked.connect(
            lambda: self.remove_task(downloading_dict["id"]))
        hbox_layout.addWidget(del_btn)

        item_widget.setLayout(hbox_layout)
        item_widget_style_sheet = f'#{downloading_dict["id"]}{{background-color:rgb(241,231,230);color:rgb(210,10,10)}}'
        item_widget.setStyleSheet(item_widget_style_sheet)
        return item_widget
Example #2
0
    def __init__(self, parent=None):
        super().__init__(parent)

        self.screen_width, self.screen_height = get_screen_res(screen)
        self.screen_res: str = f'{self.screen_width}x{self.screen_height}'
        self.payload: Dict[str, str] = {
            'sorting': 'random',
            'categories': '100',
            'atleast': self.screen_res
        }

        self.sw = StackedWidget()

        self.progressbar = ProgressBar()
        self.progressbar.hide()

        self.prev_btn = Button('angle-left.svg', key='left')
        self.next_btn = Button('angle-right.svg', key='right')
        self.update_btn = Button('sync-alt.svg', ' Update', key='r')
        self.apply_btn = Button('check.svg', 'Apply')
        self.save_btn = Button('save.svg', 'Save')

        self.prev_btn.clicked.connect(self.prev)
        self.next_btn.clicked.connect(self.next)
        self.apply_btn.clicked.connect(self.apply)
        self.update_btn.clicked.connect(self.update_)
        self.save_btn.clicked.connect(self.save)

        self.saved_msg = QLabel('Saved')
        self.image_count = QLabel()
        self.image_res = QLabel()
        self.saved_msg.setStyleSheet(f'color: {INFO_COLOR}')
        self.image_count.setStyleSheet(f'color: {INFO_COLOR}')
        self.image_res.setStyleSheet(f'color: {INFO_COLOR}')

        self.info_layout = QHBoxLayout()
        self.info_layout.addWidget(self.progressbar)
        self.info_layout.addStretch()
        self.info_layout.addWidget(self.image_count)
        self.info_layout.addWidget(self.image_res)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.prev_btn)
        button_layout.addWidget(self.next_btn)
        button_layout.addWidget(self.update_btn)
        button_layout.addWidget(self.apply_btn)
        button_layout.addWidget(self.save_btn)

        self.main_layout = QVBoxLayout()
        self.main_layout.addLayout(self.info_layout)
        self.main_layout.addWidget(self.sw)
        self.main_layout.addLayout(button_layout)
        self.setLayout(self.main_layout)

        self.sw.added.connect(self.change_image_count)
Example #3
0
 def init_progressbar(self):
     self.progressbar = ProgressBar(self,
                                    minimum=0,
                                    maximum=0,
                                    textVisible=False,
                                    objectName="RedProgressBar")
     self.progressbar.setGeometry(QRect(-10, 0, 1230, 4))
     self.progressbar.setMaximumSize(16777215, 3)
     self.progressbar.setMinimumSize(0, 2)
     self.progressbar.start()
     self.progressbar.setTextVisible(False)
     self.progressbar.setHidden(True)
Example #4
0
    def fit(self, dataset, num_epochs=1):
        qstates = self.preprocessBatching(dataset["qstates"])
        qvalues = self.preprocessBatching(dataset["qvalues"])
        idx = list(range(qstates.shape[0]))
        random.shuffle(idx)
        num_batches = len(idx) // self.batch_size

        X = nd.array(qstates[idx], ctx=self.ctx)\
            .reshape([num_batches, self.batch_size] + list(qstates.shape[1:]))
        Y = nd.array(qvalues[idx], ctx=self.ctx)\
            .reshape([num_batches, self.batch_size] + list(qvalues.shape[1:]))

        alpha = self.alpha
        progressBar = ProgressBar(maxval=num_epochs)
        for e in range(num_epochs):
            if self.progbar:
                progressBar.printProgress(e,
                                          prefix="Training Q(s,a)",
                                          suffix="%s / %s" %
                                          (e + 1, num_epochs))
            if ((e + 1) % 100) == 0:  # 100 epoch alpha decay
                alpha = alpha / 2.0

            for i in range(num_batches):
                with autograd.record():
                    outputs, hidden_states = self.nn(X[i])
                    loss = self.mean_loss(outputs, Y[i])
                    loss.backward()
                self.optimizer(self.params, alpha)

                # Keep a moving average of the losses
                if (i == 0) and (e == 0):
                    self.moving_loss = np.mean(loss.asnumpy()[0])
                else:
                    self.moving_loss = 0.99 * self.moving_loss + 0.01 * \
                        np.mean(loss.asnumpy()[0])
Example #5
0
 def build(self):
     self.panel.pack((5, 5))
     self.label = Label(self.panel, self.label)
     self.panel.pack(self.label, fill=True)
     self.progressbar = ProgressBar(self.panel)
     self.panel.pack(self.progressbar, fill=True, padding=15)
Example #6
0
class CustomProgressDialog(SimpleDialog):
    label = None
    progressbar = None
    button_box = None
    cancel_btn = None
    result = None
    callback = None
    args = None
    msg = ''

    def __init__(self, parent, title, size=(500, 100), style=VERTICAL,
                 resizable=False, action_button=const.BUTTON_CANCEL,
                 add_line=False, margin=None,
                 button_box_padding=0):
        self.label = title
        self.action_button = action_button
        self.button_box_padding = button_box_padding
        SimpleDialog.__init__(self, parent, title, size, style, resizable,
                              self.on_load, add_line, margin)

    def build(self):
        self.panel.pack((5, 5))
        self.label = Label(self.panel, self.label)
        self.panel.pack(self.label, fill=True)
        self.progressbar = ProgressBar(self.panel)
        self.panel.pack(self.progressbar, fill=True, padding=15)

    def set_dialog_buttons(self):
        self.button_box = HPanel(self.box)
        self.box.pack(self.button_box, fill=True,
                      padding_all=self.button_box_padding)
        self.button_box.pack(HPanel(self.button_box), fill=True, expand=True)
        self.cancel_btn = Button(self.button_box, '', onclick=self.on_cancel,
                                 default=True, pid=const.BUTTON_CANCEL)
        self.cancel_btn.set_enable(False)
        self.button_box.pack(self.cancel_btn)
        self.fit()

    def on_cancel(self):
        self.end_modal(const.BUTTON_CANCEL)

    def show(self):
        self.show_modal()
        return self.result

    def update_data(self, value, msg):
        self.label.set_text(msg)
        self.label.Update()
        self.progressbar.set_value(value)
        self.progressbar.Update()
        self.Update()
        wx.Yield()

    def on_load(self, *args):
        self._timer.Stop()
        self.progressbar.set_value(5)
        try:
            if self.callback and self.args:
                self.result = self.callback(*self.args)
        except Exception as e:
            LOG.exception('Error in progress dialog running: %s', e)
        finally:
            self.progressbar.set_value(98)
            self.end_modal(const.BUTTON_CANCEL)

    def run(self, callback, args):
        self.callback, self.args = callback, args
        return self.show()
Example #7
0
class KindleHelper(KindleHelperUI, QMainWindow):
    def __init__(self, parent=None):
        super(KindleHelper, self).__init__(parent)
        self.version = "1.1.0"
        self.setWindowTitle("Kindle助手")
        if os.sys.platform == 'darwin':
            self.setWindowIcon(QIcon(os.path.join(root, 'src', 'kindle.icns')))
        else:
            self.setWindowIcon(QIcon(os.path.join(root, 'src', 'logo.ico')))
        self.setupUi(self)
        self.clipboard = QApplication.clipboard()
        self.init_ui()

    def init_ui(self):
        self.init_sider_btn_groups()
        self.init_search_page()
        self.init_direct_tab()
        self.init_net_pan_tab()
        self.init_progressbar()
        self.init_systray()
        self.init_trigger()

    def init_trigger(self):
        self.downloaded_widget.send_trigger.connect(
            self.sended_page.add_sended_item)
        self.task_widget.new_task_trigger.connect(self.download)

    def init_systray(self):
        self.tray = SysTray(self)
        self.tray.trigger.connect(self.systray_trigger_callback)
        self.tray.show()

    def systray_trigger_callback(self, action_dict):
        if action_dict['visible']:
            # self.setVisible(True)
            self.show()
        if action_dict['quit']:
            # self.setVisible(False)
            self.hide()
            sys.exit()

    def init_search_page(self):
        self.search_book_lineEdit.returnPressed.connect(self.input_search)

    def init_progressbar(self):
        self.progressbar = ProgressBar(self,
                                       minimum=0,
                                       maximum=0,
                                       textVisible=False,
                                       objectName="RedProgressBar")
        self.progressbar.setGeometry(QRect(-10, 0, 1230, 4))
        self.progressbar.setMaximumSize(16777215, 3)
        self.progressbar.setMinimumSize(0, 2)
        self.progressbar.start()
        self.progressbar.setTextVisible(False)
        self.progressbar.setHidden(True)

    def init_sider_btn_groups(self):
        self.sider_page_dict = {
            "search_btn": 0,
            "new_task_btn": 1,
            "downloading_btn": 2,
            "done_btn": 3,
            "send_btn": 4,
            "about_btn": 5
        }
        self.search_btn.clicked.connect(
            lambda: self.sider_btn_checked(self.search_btn))
        self.new_task_btn.clicked.connect(
            lambda: self.sider_btn_checked(self.new_task_btn))
        self.downloading_btn.clicked.connect(
            lambda: self.sider_btn_checked(self.downloading_btn))
        self.done_btn.clicked.connect(
            lambda: self.sider_btn_checked(self.done_btn))
        self.send_btn.clicked.connect(
            lambda: self.sider_btn_checked(self.send_btn))
        self.about_btn.clicked.connect(
            lambda: self.sider_btn_checked(self.about_btn))

    def sider_btn_checked(self, btn):
        self.search_btn.setChecked(False)
        self.new_task_btn.setChecked(False)
        self.downloading_btn.setChecked(False)
        self.done_btn.setChecked(False)
        self.send_btn.setChecked(False)
        self.about_btn.setChecked(False)
        self.stackedWidget.setCurrentIndex(
            self.sider_page_dict[btn.objectName()])
        btn.setChecked(True)

    def input_search(self):
        search_keyword = self.search_book_lineEdit.text().strip()
        # self.search_book_lineEdit.setDisabled(True)
        if search_keyword == "":
            QMessageBox.warning(self, "KindleHelper", "搜索书籍名称不能为空!")
            # self.search_book_lineEdit.setDisabled(False)
            # return
        else:
            self.progressbar.setHidden(False)
            self.start_work_thread(search_keyword)

    def start_work_thread(self, keyword):
        self.search_worker = SearchWorker(keyword)
        self.search_worker.trigger.connect(self.callback_search)
        self.search_worker.start()

    def callback_search(self, download_dict):
        # self.search_book_lineEdit.setDisabled(False)
        self.progressbar.setHidden(True)
        self.callback_search_direct_tab(download_dict['direct'])
        self.callback_search_net_tab(download_dict['net'])

    def callback_search_direct_tab(self, direct_download_dict_list):
        self.direct_tab.setRowCount(0)
        row_count = 0
        for direct_download_dict in direct_download_dict_list:
            if direct_download_dict:
                key = list(direct_download_dict.keys())[0]
                self.direct_tab.insertRow(row_count)
                self.direct_tab.setRowHeight(row_count, 60)
                book_name = key
                book_size = direct_download_dict[key]['size']
                speed = direct_download_dict[key]['speed']
                download_url = direct_download_dict[key]['download']
                download_dict = {
                    "id":
                    hashlib.md5(download_url.encode('utf-8')).hexdigest(),
                    "file_name": book_name,
                    "url": download_url,
                    "size": book_size
                }
                download_btn = self.create_download_btn(download_dict)
                self.direct_tab.setItem(row_count, 0,
                                        QTableWidgetItem(book_name))
                self.direct_tab.setItem(row_count, 1,
                                        QTableWidgetItem(book_size))
                self.direct_tab.setItem(row_count, 2, QTableWidgetItem(speed))
                self.direct_tab.setCellWidget(row_count, 3, download_btn)
                row_count += 1

    def callback_search_net_tab(self, net_download_dict_list):
        self.net_pan_tab.setRowCount(0)
        row_count = 0
        for net_download_dict in net_download_dict_list:
            if net_download_dict:
                key = list(net_download_dict.keys())[0]
                self.net_pan_tab.insertRow(row_count)
                self.net_pan_tab.setRowHeight(row_count, 60)
                book_name = key
                self.net_pan_tab.setItem(row_count, 0,
                                         QTableWidgetItem(book_name))
                btn_groups_dict = self.create_net_pan_btn_groups_dict(
                    net_download_dict)
                for key in btn_groups_dict:
                    self.net_pan_tab.setCellWidget(row_count, key,
                                                   btn_groups_dict[key])
                row_count += 1

    def create_net_pan_btn_groups_dict(self, net_pan_dict):
        btn_dict = {}
        pan_dict = net_pan_dict[list(net_pan_dict.keys())[0]]
        for key in pan_dict:
            widget = QWidget()
            widget.setObjectName(
                f'{hashlib.md5(key.encode("utf-8")).hexdigest()}_widget')
            btn = QPushButton()
            btn.setStyleSheet("QPushButton{border:none}")
            btn.setToolTip('打开浏览器下载文件')
            hbox_layout = QHBoxLayout()
            hbox_layout.addWidget(btn, Qt.AlignHCenter)
            widget.setLayout(hbox_layout)
            if '百度网盘' in key:
                btn.setIcon(QIcon(os.path.join(assets, 'baidu.png')))
                btn.setObjectName(f'{key}-{pan_dict[key]}')
                btn.clicked.connect(self.copy_download_url)
                btn_dict[1] = widget
            elif '腾讯微云' == key:
                btn.setIcon(QIcon(os.path.join(assets, 'tengxun.png')))
                btn.setObjectName(f'{pan_dict[key]}')
                btn.clicked.connect(self.copy_download_url)
                btn_dict[2] = widget
            else:
                btn.setIcon(QIcon(os.path.join(assets, 'chengtong.png')))
                btn.setObjectName(f'{pan_dict[key]}')
                btn.clicked.connect(self.copy_download_url)
                btn_dict[3] = widget
        return btn_dict

    def copy_download_url(self):
        self.clipboard.setText(self.sender().objectName())
        QMessageBox.information(self, None, '下载地址成功复制到剪贴板!')

    def create_download_btn(self, download_dict):
        widget = QWidget()
        download_btn = QPushButton()
        download_btn.setIcon(QIcon(os.path.join(assets, 'download_btn.png')))
        download_btn.setObjectName("item_download_btn")
        download_btn.setStyleSheet("QPushButton#item_download_btn{\n"
                                   " border:none;}")
        download_btn.clicked.connect(
            lambda: self.download_book(download_btn, download_dict))
        hbox_layout = QHBoxLayout()
        hbox_layout.addWidget(download_btn, Qt.AlignHCenter)
        widget.setLayout(hbox_layout)
        return widget

    def init_direct_tab(self):
        self.direct_tab = QTableWidget()
        self.direct_tab.setFrameShape(QFrame.NoFrame)
        self.direct_tab.setColumnCount(4)
        self.direct_tab.horizontalHeader().setStretchLastSection(True)
        self.direct_tab.setSelectionMode(QAbstractItemView.SingleSelection)
        self.direct_tab.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.direct_tab.setHorizontalHeaderLabels(
            ['文件名称', '文件大小', '下载时间', '操作'])
        self.direct_tab.horizontalHeader().setSectionsClickable(False)
        self.direct_tab.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.direct_tab.setColumnWidth(0, 600)
        self.direct_tab.setColumnWidth(1, 100)
        self.direct_tab.setColumnWidth(2, 100)
        self.direct_tab.setColumnWidth(3, 40)
        hbox_layout = QHBoxLayout()
        hbox_layout.addWidget(self.direct_tab)
        self.direct_download.setLayout(hbox_layout)

    def init_net_pan_tab(self):
        self.net_pan_tab = QTableWidget()
        self.net_pan_tab.setFrameShape(QFrame.NoFrame)
        self.net_pan_tab.setColumnCount(4)
        self.net_pan_tab.horizontalHeader().setStretchLastSection(True)
        self.net_pan_tab.setSelectionMode(QAbstractItemView.SingleSelection)
        self.net_pan_tab.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.net_pan_tab.setHorizontalHeaderLabels(
            ['文件名称', '百度网盘', '腾讯微云', '城通网盘'])
        self.net_pan_tab.horizontalHeader().setSectionsClickable(False)
        self.net_pan_tab.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.net_pan_tab.setColumnWidth(0, 480)
        self.net_pan_tab.setColumnWidth(1, 120)
        self.net_pan_tab.setColumnWidth(2, 120)
        self.net_pan_tab.setColumnWidth(3, 120)
        hbox_layout = QHBoxLayout()
        hbox_layout.addWidget(self.net_pan_tab)
        self.netpan.setLayout(hbox_layout)

    def download_book(self, button, download_dict):
        if not self.downloading_widget.check_download(download_dict):
            QMessageBox.information(
                self, None, "当前站点同一时间只支持单个文件下载,请等待下载结束后再尝试,或者删除其他正在下载的任务!")
            return
        row = self.direct_tab.indexAt(button.pos()).row()
        self.direct_tab.removeRow(row)
        QMessageBox.about(self, None, '开始下载')
        self.download(download_dict)

    def download(self, download_dict):
        download_worker = DownloadWorker(download_dict)
        download_worker.trigger.connect(self.callback_download)
        download_worker.download_trigger.connect(
            self.callback_download_progress)
        download_worker.start()
        self.downloading_widget.add_downloading_item(
            download_dict, lambda: download_worker.terminate())

    def callback_download(self, download_return_list):
        finish_or_not, download_dict = download_return_list
        if finish_or_not is None:
            return
        msg = f'{download_dict["file_name"]}下载失败!'
        if finish_or_not:
            msg = f'{download_dict["file_name"]}下载完成!'
            self.downloading_widget.remove_task(download_dict['id'])
            self.downloaded_widget.add_downloaded_item(download_dict)
        QMessageBox.information(self, None, msg)

    def callback_download_progress(self, download_progress_dict):
        self.downloading_widget.update_progress(download_progress_dict)

    def closeEvent(self, event):
        quit_flag = QMessageBox.question(self, '退出确认', '确认退出应用程序?',
                                         QMessageBox.Yes | QMessageBox.No)
        event.ignore()
        if quit_flag == QMessageBox.Yes:
            event.accept()
            sys.exit()
        else:
            # self.setVisible(False)
            self.hide()
Example #8
0
class Changewall(QDialog):
    """ Parent of all the widgets """
    def __init__(self, parent=None):
        super().__init__(parent)

        self.screen_width, self.screen_height = get_screen_res(screen)
        self.screen_res: str = f'{self.screen_width}x{self.screen_height}'
        self.payload: Dict[str, str] = {
            'sorting': 'random',
            'categories': '100',
            'atleast': self.screen_res
        }

        self.sw = StackedWidget()

        self.progressbar = ProgressBar()
        self.progressbar.hide()

        self.prev_btn = Button('angle-left.svg', key='left')
        self.next_btn = Button('angle-right.svg', key='right')
        self.update_btn = Button('sync-alt.svg', ' Update', key='r')
        self.apply_btn = Button('check.svg', 'Apply')
        self.save_btn = Button('save.svg', 'Save')

        self.prev_btn.clicked.connect(self.prev)
        self.next_btn.clicked.connect(self.next)
        self.apply_btn.clicked.connect(self.apply)
        self.update_btn.clicked.connect(self.update_)
        self.save_btn.clicked.connect(self.save)

        self.saved_msg = QLabel('Saved')
        self.image_count = QLabel()
        self.image_res = QLabel()
        self.saved_msg.setStyleSheet(f'color: {INFO_COLOR}')
        self.image_count.setStyleSheet(f'color: {INFO_COLOR}')
        self.image_res.setStyleSheet(f'color: {INFO_COLOR}')

        self.info_layout = QHBoxLayout()
        self.info_layout.addWidget(self.progressbar)
        self.info_layout.addStretch()
        self.info_layout.addWidget(self.image_count)
        self.info_layout.addWidget(self.image_res)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.prev_btn)
        button_layout.addWidget(self.next_btn)
        button_layout.addWidget(self.update_btn)
        button_layout.addWidget(self.apply_btn)
        button_layout.addWidget(self.save_btn)

        self.main_layout = QVBoxLayout()
        self.main_layout.addLayout(self.info_layout)
        self.main_layout.addWidget(self.sw)
        self.main_layout.addLayout(button_layout)
        self.setLayout(self.main_layout)

        self.sw.added.connect(self.change_image_count)

    def prev(self) -> None:
        """ Show previous image in stacked widget """
        current_index: int = self.sw.currentIndex()
        if current_index > 0:
            self.sw.setCurrentIndex(current_index - 1)
        logger.debug(
            f"Stacked widget's current index is {self.sw.currentIndex()}")
        self.change_info()

    def next(self) -> None:
        """ Show next image in stacked widget """
        current_index: int = self.sw.currentIndex()
        self.sw.setCurrentIndex(current_index + 1)
        logger.debug(
            f"Stacked widget's current index is {self.sw.currentIndex()}")
        self.change_info()

    def update_(self) -> None:
        """
        Download new json, new thumbnails and delete old ones
        with clearing stacked widget
        """
        for file in THUMBS_DIR.iterdir():
            logger.debug(f'Deleting {short_path(file)}')
            file.unlink()

        # Clear stacked widget
        for _ in range(self.sw.count()):
            widget = self.sw.widget(0)
            self.sw.removeWidget(widget)
            del widget

        download = Download(JSON_FILE,
                            APP_DIR,
                            SEARCH_URL,
                            payload=self.payload)
        download.save()

        self.progressbar.show()
        self.download_thumbs()

    def apply(self) -> None:
        """ Set current image as wallpaper """
        for file in CURRENT_DIR.iterdir():
            file.unlink()
            logger.debug(f'Deleted {short_path(file)}')

        image_id: str = self.sw.current_image_id()
        info: Dict[str, str] = image_info(image_id)
        image: Path = Path(info['image_id'] + info['extension'])

        self.progressbar.show()
        download = Download(image,
                            CURRENT_DIR,
                            info['full_image_url'],
                            stream=True)
        download.finished_chunk.connect(self.set_progressbar)
        download.finished_file.connect(set_wall)
        download.save()

    def save(self) -> None:
        """
        Save image to CURRENT_DIR
        When image is saved, show Saved label
        """
        image_id: str = self.sw.current_image_id()
        info: Dict[str, str] = image_info(image_id)
        image: Path = Path(info['image_id'] + info['extension'])

        self.progressbar.show()
        download = Download(image,
                            SAVED_DIR,
                            info['full_image_url'],
                            stream=True)
        download.finished_chunk.connect(self.set_progressbar)
        download.save()

        # Show message "Saved" for 3 seconds in info layout
        self.info_layout.insertWidget(2, self.saved_msg)
        self.saved_msg.show()
        QTimer.singleShot(3000, self.hide_msg)

        save_msg: bool = config.getboolean('Program', 'show_save_message')

        def disable_save_msg():
            config['Program']['show_save_message'] = 'no'
            config_save()
            logger.debug('Save message is now disabled')

        # Create and show "save message box" if it is set to True
        if save_msg:
            msgBox = QMessageBox(self)
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setText('Saved')
            msgBox.setInformativeText(
                f'The image has been saved to \n{str(SAVED_DIR)}')
            msgBox.setStandardButtons(QMessageBox.Ok)
            dontshow_btn = msgBox.addButton("Don't show again",
                                            QMessageBox.ActionRole)
            dontshow_btn.clicked.connect(disable_save_msg)
            msgBox.exec_()

    def hide_msg(self) -> None:
        """ Remove save label from info layout and hide it """
        self.info_layout.removeWidget(self.saved_msg)
        self.saved_msg.hide()

    def download_thumbs(self) -> None:
        """
        Parse JSON_FILE then download thumbnails asynchronously.

        Each time thumbnail is downloaded, signals are emitted to
        stacked widget and progressbar
        """
        with open(JSON_FILE, 'r') as f:
            data: Dict = json.load(f)
            for item in data['data']:
                url: str = item['thumbs']['large']
                name: Path = Path(item['id'] + '.' + url[-3:])
                dt = DownloadThread(name, THUMBS_DIR, url)
                dt.finished_file.connect(self.sw.add)
                dt.finished_file.connect(self.set_progressbar)
                QThreadPool.globalInstance().start(dt)

    def change_image_count(self) -> None:
        """
        Update info of current image position in stacked widget
        and total number of images
        """
        self.image_count.setText(self.sw.count_info())

    def change_info(self) -> None:
        """
        Everytime change_info is called
        it get info of current image to
        update label 'image_res' with
        image resolution and image
        position in stacked widget
        """
        info: Dict[str, str] = image_info(self.sw.current_image_id())
        self.change_image_count()
        if len(info) > 0:
            self.image_res.setText(info['resolution'])
        else:
            self.image_res.setText('Image info not found')

    def set_progressbar(self, _) -> None:
        """
        Update progressbar and hide it
        when it reaches its maximum
        """
        current: int = self.progressbar.value()
        self.progressbar.setValue(current + 1)
        if current == self.progressbar.maximum():
            self.progressbar.hide()
            self.progressbar.setValue(0)

    def load(self) -> None:
        """
        Download thumbnails if THUMBS_DIR is empty
        or JSON_FILE don't exist.
        Otherwise fill stacked widget with existing thumbnails
        """
        create_dirs(THUMBS_DIR, CURRENT_DIR, SAVED_DIR)

        if JSON_FILE.exists():
            if not is_dir_contains_images(THUMBS_DIR):
                logger.debug(
                    f"{short_path(THUMBS_DIR)} is empty. Downloading new thumbnails"
                )
                self.progressbar.show()
                self.download_thumbs()
            else:
                logger.debug('Filling stacked widget')
                self.sw.fill()
                self.change_info()
        else:
            logger.debug(f"{short_path(JSON_FILE)} doesn't exist. Updating")
            self.update_()

    def resize_move(self) -> None:
        """ Resize and move window using parameters from settings """
        try:
            self.resize(*win_size)
            logger.debug(f'Resized window to {win_size}')
        except:
            logger.warning('Could not resize window')

        if win_pos:
            try:
                self.move(*win_pos)
                logger.debug(f'Moved window to {win_pos}')
            except:
                logger.warning('Could not move window to a new position')

    def closeEvent(self, event) -> None:
        """ Save window size and position before closing the window"""
        config['Program']['window_size'] = f'{self.width()}, {self.height()}'
        config['Program']['window_position'] = f'{self.x()}, {self.y()}'
        config_save()
Example #9
0
def main():
    # define arguments
    parser = argparse.ArgumentParser()
    parser.add_argument("--render",
                        action="store_true",
                        help="Render the state")
    parser.add_argument("--render_interval",
                        type=int,
                        default=10,
                        help="Number of rollouts to skip before rendering")
    parser.add_argument("--num_rollouts",
                        type=int,
                        default=-1,
                        help="Number of max rollouts")
    parser.add_argument("--logfile",
                        type=str,
                        help="Indicate where to save rollout data")
    parser.add_argument(
        "--load_params",
        type=str,
        help="Load previously learned parameters from [LOAD_PARAMS]")
    parser.add_argument("--save_params",
                        type=str,
                        help="Save learned parameters to [SAVE_PARAMS]")
    parser.add_argument("--silent",
                        action="store_true",
                        help="Suppress print of the DQN config")
    parser.add_argument("--gamma",
                        type=float,
                        default=0.99,
                        help="Discount factor")
    parser.add_argument("--epsilon",
                        type=float,
                        default=0.1,
                        help="Random factor (for Epsilon-greedy)")
    parser.add_argument("--eps_anneal",
                        type=int,
                        default=0,
                        help="The amount of episodes to anneal epsilon by")
    parser.add_argument("--sample_size",
                        type=int,
                        default=256,
                        help="Number of samples from the dataset per episode")
    parser.add_argument("--num_epochs",
                        type=int,
                        default=50,
                        help="Number of epochs to run per episode")
    parser.add_argument("--episode_length",
                        type=int,
                        default=128,
                        help="Number of rollouts per episode")
    parser.add_argument("--noise",
                        type=float,
                        help="Amount of noise to add to the actions")
    parser.add_argument("--test", action="store_true", help="Test the params")
    args = parser.parse_args()

    signal.signal(signal.SIGINT, stopsigCallback)
    global stopsig

    # create the basketball environment
    env = BasketballVelocityEnv(fps=60.0,
                                timeInterval=1.0,
                                goal=[0, 5, 0],
                                initialLengths=np.array([0, 0, 1, 1, 1, 0, 1]),
                                initialAngles=np.array(
                                    [0, 45, -20, -20, 0, -20, 0]))

    # create space
    stateSpace = ContinuousSpace(ranges=env.state_range())
    actionSpace = DiscreteSpace(intervals=[25 for i in range(7)] + [1],
                                ranges=env.action_range())
    processor = DQNProcessor(actionSpace)

    # create the model and policy functions
    modelFn = DQNNetwork(
        sizes=[stateSpace.n + actionSpace.n, 128, 256, 256, 128, 1],
        alpha=0.001,
        use_gpu=True,
        momentum=0.9)
    if args.load_params:
        print("Loading params...")
        modelFn.load_params(args.load_params)

    allActions = actionSpace.sampleAll()
    policyFn = EpsilonGreedyPolicy(
        epsilon=args.epsilon if not args.test else 0,
        getActionsFn=lambda state: allActions,
        distributionFn=lambda qstate: modelFn(qstate),
        processor=processor)
    replayBuffer = RingBuffer(max_limit=2048)
    if args.logfile:
        log = open(args.logfile, "a")

    if not args.silent:
        print("Env space range:", env.state_range())
        print("Env action range:", env.action_range())
        print("State space:", stateSpace.n)
        print("Action space:", actionSpace.n)
        print("Action space bins:", actionSpace.bins)
        print("Epsilon:", args.epsilon)
        print("Epsilon anneal episodes:", args.eps_anneal)
        print("Gamma:", args.gamma)
        __actionShape = policyFn.getActions(None).shape
        totalActions = np.prod(actionSpace.bins)
        print("Actions are sampled:", __actionShape[0] != totalActions)
        print("Number of actions:", totalActions)

    rollout = 0
    if not args.silent and not args.test:
        iterationBar = ProgressBar(maxval=args.episode_length)
    while args.num_rollouts == -1 or rollout < args.num_rollouts:
        if stopsig: break
        if not args.silent and not args.test:
            iterationBar.printProgress(rollout % args.episode_length,
                                       prefix="Query(s,a,s',r)",
                                       suffix="epsilon: " +
                                       str(policyFn.epsilon))
        state = env.reset()
        reward = 0
        done = False
        steps = 0
        while not done and steps < 5:  # 5 step max
            action = policyFn(state)
            if steps == 4:  # throw immediately
                action[-2] = 0
                action[-1] = 1
            envAction = processor.process_env_action(action)
            if args.noise:
                envAction[:7] += np.random.normal(scale=np.ones([7]) *
                                                  args.noise)
            nextState, reward, done, info = env.step(envAction)
            replayBuffer.append([state, action, nextState, reward, done])
            if args.test and done: print("Reward:", reward)
            state = nextState
            steps += 1
            if args.render and (rollout + 1) % args.render_interval == 0:
                env.render()

        rollout += 1
        if args.eps_anneal > 0:  # linear anneal
            epsilon_diff = args.epsilon - min(0.1, args.epsilon)
            policyFn.epsilon = args.epsilon - min(rollout, args.eps_anneal) / \
                float(args.eps_anneal) * epsilon_diff

        if rollout % args.episode_length == 0 and not args.test:
            dataset = replayBuffer.sample(args.sample_size)
            states = np.array([d[0] for d in dataset])
            actions = np.array([d[1] for d in dataset])
            nextStates = [d[2] for d in dataset]
            rewards = np.array([[d[3]]
                                for d in dataset])  # rewards require extra []
            terminal = [d[4] for d in dataset]

            QS0 = processor.process_Qstate(states, actions)
            Q1 = np.zeros(rewards.shape, dtype=np.float32)
            if not args.silent:
                progressBar = ProgressBar(maxval=len(nextStates))
            for i, nextState in enumerate(nextStates):
                if stopsig: break
                if not args.silent:
                    progressBar.printProgress(i,
                                              prefix="Creating Q(s,a)",
                                              suffix="%s / %s" %
                                              (i + 1, len(nextStates)))
                if terminal[i]: continue  # 0
                dist = modelFn(
                    processor.process_Qstate(
                        repmat(nextState, allActions.shape[0], 1), allActions))
                Q1[i, 0] = np.max(dist)  # max[a' in A]Q(s', a')
            if stopsig: break
            Q0_ = rewards + args.gamma * Q1
            modelFn.fit({
                "qstates": QS0,
                "qvalues": Q0_
            },
                        num_epochs=args.num_epochs)

            avgQ = np.sum(Q0_) / Q0_.shape[0]
            avgR = np.sum(rewards) / rewards.shape[0]
            print("Rollouts:", rollout, "Error:", modelFn.score(),
                  "Average Q:", avgQ, "Average R:", avgR)
            print("")
            if args.logfile:
                log.write("[" + str(rollout) + ", " + str(modelFn.score()) +
                          ", " + str(avgQ) + ", " + str(avgR) + "]\n")

    if args.logfile:
        log.close()
    if args.save_params:
        print("Saving params...")
        modelFn.save_params(args.save_params)