From 722a91f1d2e318aad0dafc0caa7a3ac5e8e6bba5 Mon Sep 17 00:00:00 2001 From: Charlotte Weaver Date: Tue, 9 Jul 2019 10:46:13 -0700 Subject: [PATCH] remove options widget + launch on file selection (#839) * remove options widget + launch on file selection * extend drop area width --- server/gui/main.py | 71 ++++++++--------------------------- server/gui/options_parser.py | 27 ------------- server/test/test_gui_utils.py | 32 ---------------- server/utils/errors.py | 7 ---- 4 files changed, 16 insertions(+), 121 deletions(-) delete mode 100644 server/gui/options_parser.py delete mode 100644 server/test/test_gui_utils.py delete mode 100644 server/utils/errors.py diff --git a/server/gui/main.py b/server/gui/main.py index c827c082..4aedf8af 100644 --- a/server/gui/main.py +++ b/server/gui/main.py @@ -14,11 +14,8 @@ from PySide2.QtWidgets import * import server.gui.cellxgene_rc from server.gui.browser import CefWidget, CefApplication -from server.gui.options_parser import parse_opt_string -from server.cli.launch import parse_engine_args from server.gui.workers import Worker, SiteReadyWorker from server.gui.utils import WINDOWS, LINUX, MAC, FileLoadSignals, Emitter, WorkerSignals, FileChanged -from server.utils.errors import OptionsError from server.utils.utils import find_available_port if WINDOWS or LINUX: @@ -30,6 +27,7 @@ if WINDOWS or LINUX: # TODO remember this or calculate it? WIDTH = 1300 HEIGHT = 800 +MAX_CONTENT_WIDTH = 700 GUI_PORT = find_available_port("localhost") BROWSER_INDEX = 0 LOAD_INDEX = 1 @@ -149,9 +147,8 @@ class LoadWidget(QFrame): def __init__(self, parent): super(LoadWidget, self).__init__(parent=parent) # Init layout - self.MAX_CONTENT_WIDTH = 500 load_ui_layout = QVBoxLayout() - h_margin = (WIDTH - self.MAX_CONTENT_WIDTH) // 2 + h_margin = (WIDTH - MAX_CONTENT_WIDTH) // 2 if h_margin < 10: h_margin = 10 load_ui_layout.setContentsMargins(h_margin, 20, h_margin, 20) @@ -178,17 +175,14 @@ class LoadWidget(QFrame): self.file_area = FileArea() self.file_name.signals.changed.connect(self.updatePath) - self.launch_widget = QPushButton("Launch cellxgene") - self.launch_widget.setEnabled(False) - self.launch_widget.clicked.connect(self.onLoad) + self.launch_widget = QLabel("Select a file to launch cellxgene") + # self.launch_widget.setEnabled(False) + # self.launch_widget.clicked.connect(self.onLoad) self.progress = QProgressBar() self.progress.setTextVisible(False) - self.advanced_options = CLIOptionsArea(self) - file_layout.addWidget(self.file_area) - file_layout.addWidget(self.advanced_options) self.loading_layout = QStackedLayout() self.loading_layout.addWidget(self.launch_widget) self.loading_layout.addWidget(self.progress) @@ -198,7 +192,7 @@ class LoadWidget(QFrame): # Error section self.error_label = QLabel("") self.error_label.setWordWrap(True) - self.error_label.setFixedWidth(self.MAX_CONTENT_WIDTH) + self.error_label.setFixedWidth(MAX_CONTENT_WIDTH) message_layout.addWidget(self.error_label) # Options Form @@ -225,14 +219,13 @@ class LoadWidget(QFrame): self.file_area.label.setText("File: " + file_name) else: self.file_area.label.setText("") - self.launch_widget.setEnabled(bool(file_name)) + # self.launch_widget.setEnabled(bool(file_name)) def reset(self): self.loading_layout.setCurrentIndex(0) self.timer.stop() self.error_label.setText("") self.file_name.updateValue(None) - self.advanced_options.reset() def updateProgress(self): curr_val = self.progress.value() @@ -240,23 +233,15 @@ class LoadWidget(QFrame): self.progress.setValue(next_val) def resetProgress(self): - print("here i am") self.progress.setValue(0) self.loading_layout.setCurrentIndex(0) self.timer.stop() def createScanpyEngine(self, file_name): - try: - self.advanced_options.parse() - except OptionsError as e: - self.signals.error.emit(f"Options Error: {e}") - return - title = self.advanced_options.title - if not title: - title = splitext(basename(file_name))[0] + title = splitext(basename(file_name))[0] self.window().setupServer() worker = Worker(self.window().parent_conn, self.window().child_conn, file_name, host="127.0.0.1", - port=GUI_PORT, title=title, engine_options=self.advanced_options.engine_options) + port=GUI_PORT, title=title, engine_options={}) self.window().load_emitter.signals.ready.connect(self.onDataReady) self.window().load_emitter.signals.engine_error.connect(self.onServerError) self.window().load_emitter.signals.server_error.connect(self.onServerError) @@ -299,37 +284,11 @@ class LoadWidget(QFrame): self.resetProgress() self.window().stacked_layout.setCurrentIndex(LOAD_INDEX) self.error_label.setText(f"Error: {err}") - self.error_label.resize(self.MAX_CONTENT_WIDTH, self.error_label.height()) + self.error_label.resize(MAX_CONTENT_WIDTH, self.error_label.height()) self.window().repaint() onServerError = partialmethod(onError, server_error=True) -class CLIOptionsArea(QFrame): - def __init__(self, parent): - super(CLIOptionsArea, self).__init__(parent) - self.engine_options = {} - self.setFixedWidth(500) - self.title = None - self.form_layout = QFormLayout() - self.form_layout.setContentsMargins(0,0,0,0) - self.cli_label = QLabel("CLI Options:") - self.cli_label.setToolTip("Additional options can be passed as cli parameters. See cellxgene --help for more info") - self.cli_widget = QLineEdit() - self.form_layout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) - self.form_layout.addRow(self.cli_label, self.cli_widget) - self.setLayout(self.form_layout) - - def reset(self): - self.cli_widget.setText("") - self.engine_options = {} - self.title = None - - def parse(self): - opts = parse_opt_string(self.cli_widget.text()) - self.title = opts.pop("title", None) - self.engine_options = parse_engine_args(**opts) - - class FilePath(QObject): def __init__(self): super(FilePath, self).__init__() @@ -346,17 +305,17 @@ class FileArea(QFrame): super(FileArea, self).__init__() self.setFrameShape(QFrame.Box) self.setMinimumHeight(100) - self.setFixedWidth(500) + self.setFixedWidth(MAX_CONTENT_WIDTH) self.setAcceptDrops(True) self.instructions = QLabel(self) self.instructions.setText("Drag & Drop a h5ad file to load or open") - self.instructions.setGeometry(10, 10, 500, self.instructions.height()) + self.instructions.setGeometry(10, 10, MAX_CONTENT_WIDTH, self.instructions.height()) self.loadButton = QPushButton("Open...", parent=self) - x_pos = (500 - self.loadButton.width()) / 2 + x_pos = (MAX_CONTENT_WIDTH - self.loadButton.width()) / 2 self.loadButton.setGeometry(x_pos, 50, self.loadButton.width(), self.loadButton.height()) self.loadButton.clicked.connect(self.fileBrowse) self.label = QLabel(self) - self.label.setGeometry(10, 75, 500, self.label.height()) + self.label.setGeometry(10, 75, MAX_CONTENT_WIDTH, self.label.height()) def fileBrowse(self): options = QFileDialog.Options() @@ -365,6 +324,7 @@ class FileArea(QFrame): "Open H5AD File", "", "H5AD Files (*.h5ad)", options=options) if file_name: self.parent().file_name.updateValue(file_name) + self.parent().onLoad() def dragEnterEvent(self, e): if e.mimeData().hasUrls: @@ -391,6 +351,7 @@ class FileArea(QFrame): for url in e.mimeData().urls(): file_name = str(url.toLocalFile()) self.parent().file_name.updateValue(file_name) + self.parent().onLoad() else: e.ignore() diff --git a/server/gui/options_parser.py b/server/gui/options_parser.py deleted file mode 100644 index ba0e64a1..00000000 --- a/server/gui/options_parser.py +++ /dev/null @@ -1,27 +0,0 @@ -import shlex - -import click - -from server.cli.launch import common_args -from server.utils.errors import OptionsError - - -@click.command() -@common_args -def cli(**kwargs): - pass - - -def parse_opt_string(opts): - context = click.Context(cli) - parser = click.OptionParser(context) - for command in context.command.params: - command.add_to_parser(parser, context) - - try: - opts, args, param_order = parser.parse_args(shlex.split(opts)) - for param in cli.params: - value, args = param.handle_parse_result(context, opts, args) - except click.ClickException as ce: - raise OptionsError(ce.message) from ce - return dict(context.params) diff --git a/server/test/test_gui_utils.py b/server/test/test_gui_utils.py deleted file mode 100644 index ca313c52..00000000 --- a/server/test/test_gui_utils.py +++ /dev/null @@ -1,32 +0,0 @@ -import unittest - -from server.gui.options_parser import parse_opt_string -from server.utils.errors import OptionsError - -default_opts = {'title': None, 'layout': (), 'obs_names': None, 'var_names': None, 'max_category_items': 1000, - 'diffexp_lfc_cutoff': 0.01} - - -class UtilsTest(unittest.TestCase): - - def test_empty_opts(self): - result = parse_opt_string("") - self.assertEqual(result, default_opts) - - def test_one_opts(self): - result = parse_opt_string("--title abcde") - expected_opts = dict(default_opts) - expected_opts["title"] = "abcde" - self.assertEqual(result, expected_opts) - - def test_malformed_opts(self): - with self.assertRaises(OptionsError): - parse_opt_string("--ewwwww lkafsjkl") - - def test_complex_opts(self): - result = parse_opt_string( - "--title abcde --obs-names zzzzz --var-names 'xxx yyy' --max-category-items 234907 " - "--diffexp-lfc-cutoff 0.00003847382") - expected_opts = {'title': 'abcde', 'layout': (), 'obs_names': 'zzzzz', 'var_names': 'xxx yyy', - 'max_category_items': 234907, 'diffexp_lfc_cutoff': 3.847382e-05} - self.assertEqual(result, expected_opts) diff --git a/server/utils/errors.py b/server/utils/errors.py deleted file mode 100644 index adf78093..00000000 --- a/server/utils/errors.py +++ /dev/null @@ -1,7 +0,0 @@ -class OptionsError(Exception): - """ - Raised when user specified cli options specified fail parsing - """ - - def __init__(self, message): - self.message = message