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
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 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 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])
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)
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()
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()
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()
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)