remove options widget + launch on file selection (#839)

* remove options widget + launch on file selection

* extend drop area width
This commit is contained in:
Charlotte Weaver
2019-07-09 10:46:13 -07:00
committed by GitHub
parent acdc810f82
commit 722a91f1d2
4 changed files with 16 additions and 121 deletions
+16 -55
View File
@@ -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()
-27
View File
@@ -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)
-32
View File
@@ -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)
-7
View File
@@ -1,7 +0,0 @@
class OptionsError(Exception):
"""
Raised when user specified cli options specified fail parsing
"""
def __init__(self, message):
self.message = message