def _set_annotation_files(self): dir_name, _ = os.path.split(self._file_name) genes_path = os.path.join(dir_name, "genes.tsv") if os.path.isfile(genes_path): self.col_annotation_file = RecentPath.create(genes_path, []) barcodes_path = os.path.join(dir_name, "barcodes.tsv") if os.path.isfile(barcodes_path): self.row_annotation_file = RecentPath.create(barcodes_path, [])
def addRecentPath(self, path): """ Prepend a path entry to the list of recent paths If an entry with the same path already exists in the recent path list it is moved to the first place Parameters ---------- path : str """ existing = None for pathitem in self.recent_paths: try: if os.path.samefile(pathitem.abspath, path): existing = pathitem break except FileNotFoundError: # file not found if the `pathitem.abspath` no longer exists pass model = self.recent_cb.model() if existing is not None: selected_index = self.recent_paths.index(existing) assert model.item(selected_index).data(Qt.UserRole) is existing self.recent_paths.remove(existing) row = model.takeRow(selected_index) self.recent_paths.insert(0, existing) model.insertRow(0, row) else: item = RecentPath.create(path, self._search_paths()) self.recent_paths.insert(0, item) model.insertRow(0, RecentPath_asqstandarditem(item)) return 0
def set_current_path(self, path): if samepath(self._current_path, path): return model = self.recent_model index = -1 pathitem = None for i in range(model.rowCount()): item = model.item(i) data = item.data(Qt.UserRole) if item is not None else None if isinstance(data, RecentPath) and samepath(path, data.abspath): index, pathitem = i, data break rpaths = [] if pathitem is None: assert index == -1 pathitem = RecentPath.create(path, rpaths) if index != -1: item = model.takeRow(index) else: item = RecentPath_asqstandarditem(pathitem) model.insertRow(0, item) self._current_path = path self.recent_combo.setCurrentIndex(0) self._data_loader = get_data_loader(path) self._update_summary() self.setup_gui() self._invalidate()
def add_path(self, filename, reader): """Add (or move) a file name to the top of recent paths""" self._check_init() recent = RecentPath.create(filename, self._search_paths()) if reader is not None: recent.file_format = reader.qualified_name() self.recent_paths.append(recent)
def _relocate_recent_files(self): search_paths = self._search_paths() rec = [] for recent in self.recent_paths: kwargs = dict( title=recent.title, sheet=recent.sheet, file_format=recent.file_format) resolved = recent.resolve(search_paths) if resolved is not None: rec.append( RecentPath.create(resolved.abspath, search_paths, **kwargs)) else: rec.append(recent) # change the list in-place for the case the widgets wraps this list self.recent_paths[:] = rec
def browse_col_annotations(self): dlg = QFileDialog(self, acceptMode=QFileDialog.AcceptOpen, fileMode=QFileDialog.ExistingFile) filters = AnnotationFormats dlg.setNameFilters(filters) if filters: dlg.selectNameFilter(filters[0]) if dlg.exec_() == QFileDialog.Accepted: filename = dlg.selectedFiles()[0] m = self.col_annotations_combo.model() # type: QStandardItemModel pathitem = RecentPath.create(filename, []) index = insert_recent_path(m, pathitem) self.col_annotations_combo.setCurrentIndex(index) self._invalidate()
def _relocate_recent_files(self): search_paths = self._search_paths() rec = [] for recent in self.recent_paths: kwargs = dict(title=recent.title, sheet=recent.sheet, file_format=recent.file_format) resolved = recent.resolve(search_paths) if resolved is not None: rec.append( RecentPath.create(resolved.abspath, search_paths, **kwargs)) else: rec.append(recent) # change the list in-place for the case the widgets wraps this list self.recent_paths[:] = rec
def set_current_path(self, path): if samepath(self._current_path, path): return model = self.recent_model index = -1 pathitem = None for i in range(model.rowCount()): item = model.item(i) data = item.data(Qt.UserRole) if item is not None else None if isinstance(data, RecentPath) and samepath(path, data.abspath): index, pathitem = i, data break rpaths = [] if pathitem is None: assert index == -1 pathitem = RecentPath.create(path, rpaths) if index != -1: item = model.takeRow(index) else: item = RecentPath_asqstandarditem(pathitem) # TODO: Restore or guess load options if path.endswith(".count"): self.set_header_rows_count(1) self.set_header_cols_count(1) enabled = False else: enabled = True self.header_rows_spin.setEnabled(enabled) self.header_cols_spin.setEnabled(enabled) model.insertRow(0, item) self._current_path = path self.recent_combo.setCurrentIndex(0) self._update_summary() self._invalidate()
def __init__(self, file_name=""): # file parameters self._file_name = file_name self._recent_path = RecentPath.create(file_name, []) self.file_size = None self.n_rows = None self.n_cols = None self.sparsity = None self._set_file_size() self._set_file_parameters() # reading parameters self._leading_cols = 0 self._leading_rows = 0 self._use_rows_mask = None self._use_cols_mask = None self._row_annot_header = 0 self._row_annot_columns = None self._col_annot_header = 0 self._col_annot_columns = None # GUI parameters self.FIXED_FORMAT = True self.ENABLE_ANNOTATIONS = True self.header_rows_count = None self.header_cols_count = None self.transposed = None self.sample_rows_enabled = None self.sample_cols_enabled = None self.sample_rows_p = None self.sample_cols_p = None self.row_annotations_enabled = True self.row_annotation_file = None # type: RecentPath self.col_annotations_enabled = True self.col_annotation_file = None # type: RecentPath # errors self.errors = {} # type: Dict[str, Tuple] self.__reset_error_messages()
def set_current_path(self, path): if samepath(self._current_path, path): return model = self.recent_model index = -1 pathitem = None for i in range(model.rowCount()): item = model.item(i) data = item.data(Qt.UserRole) if item is not None else None if isinstance(data, RecentPath) and samepath(path, data.abspath): index, pathitem = i, data break rpaths = [] if pathitem is None: assert index == -1 pathitem = RecentPath.create(path, rpaths) if index != -1: item = model.takeRow(index) else: item = RecentPath_asqstandarditem(pathitem) opts = infer_options(path) if path.endswith(".count"): self.set_header_rows_count(1) self.set_header_cols_count(1) fixed_format = False elif path.endswith(".mtx"): self.set_header_rows_count(0) self.set_header_cols_count(0) fixed_format = False self._cells_in_rows = False else: fixed_format = True if opts.transposed is not None: self._cells_in_rows = not opts.transposed self.data_struct_box.setEnabled(fixed_format) self.header_rows_spin.setEnabled(fixed_format) self.header_cols_spin.setEnabled(fixed_format) model.insertRow(0, item) self._current_path = path self.recent_combo.setCurrentIndex(0) self._update_summary() if opts.row_annotation_file is not None: index = insert_recent_path( self.row_annotations_combo.model(), RecentPath.create(opts.row_annotation_file, [])) self.row_annotations_combo.setCurrentIndex(index) self.set_row_annotations_enabled(True) else: self.row_annotations_combo.setCurrentIndex(-1) if opts.column_annotation_file is not None: index = insert_recent_path( self.col_annotations_combo.model(), RecentPath.create(opts.column_annotation_file, [])) self.col_annotations_combo.setCurrentIndex(index) self.set_col_annotations_enabled(True) else: self.col_annotations_combo.setCurrentIndex(-1) if path.endswith(".mtx") \ and opts.row_annotation_file is not None \ and opts.column_annotation_file is not None \ and os.path.basename(opts.row_annotation_file) == "barcodes.tsv" \ and os.path.basename(opts.column_annotation_file) == "genes.tsv": # 10x gene-barcode matrix # TODO: The genes/barcodes files should be unconditionally loaded # alongside the mtx. The row/col annotations might be used to # specify additional sources. For the time being they are put in # the corresponding comboboxes and made uneditable. self.annotation_files_box.setEnabled(False) else: self.annotation_files_box.setEnabled(True) self._invalidate()
def __init__(self): super().__init__() self._current_path = "" icon_open_dir = self.style().standardIcon(QStyle.SP_DirOpenIcon) # Top grid with file selection combo box grid = QGridLayout() lb = QLabel("File:") lb.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.recent_combo = cb = QComboBox( sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon, minimumContentsLength=20, toolTip="Select a recent file") self.recent_model = cb.model() # type: QStandardItemModel self.recent_combo.activated[int].connect(self._select_recent) browse = QPushButton("...", autoDefault=False, icon=icon_open_dir, clicked=self.browse) # reload = QPushButton("Reload", autoDefault=False, icon=icon_reload) grid.addWidget(lb, 0, 0, Qt.AlignVCenter) grid.addWidget(cb, 0, 1) grid.addWidget(browse, 0, 2) # grid.addWidget(reload, 0, 3) self.summary_label = label = QLabel("", self) label.ensurePolished() f = label.font() if f.pointSizeF() != -1: f.setPointSizeF(f.pointSizeF() * 5 / 6) else: f.setPixelSize(f.pixelSize() * 5 / 6) label.setFont(f) grid.addWidget(label, 1, 1, 1, 3) self.controlArea.layout().addLayout(grid) box = gui.widgetBox(self.controlArea, "Headers and Row Labels", spacing=-1) hl = QHBoxLayout() hl.setContentsMargins(0, 0, 0, 0) self.header_rows_spin = spin = QSpinBox(box, minimum=0, maximum=3, value=self._header_rows_count, keyboardTracking=False) spin.valueChanged.connect(self.set_header_rows_count) hl.addWidget(QLabel("Data starts with", box)) hl.addWidget(self.header_rows_spin) hl.addWidget(QLabel("header row(s)", box)) hl.addStretch(10) box.layout().addLayout(hl) hl = QHBoxLayout() hl.setContentsMargins(0, 0, 0, 0) self.header_cols_spin = spin = QSpinBox(box, minimum=0, maximum=3, value=self._header_cols_count, keyboardTracking=False) spin.valueChanged.connect(self.set_header_cols_count) hl.addWidget(QLabel("First", box)) hl.addWidget(self.header_cols_spin) hl.addWidget(QLabel("column(s) are row labels", box)) hl.addStretch(10) box.layout().addLayout(hl) self.data_struct_box = box = gui.widgetBox(self.controlArea, "Input Data Structure") gui.radioButtons(box, self, "_cells_in_rows", [ "Genes in rows, samples in columns", "Samples in rows, genes in columns" ], callback=self._invalidate) box = gui.widgetBox(self.controlArea, "Sample Data", spacing=-1) grid = QGridLayout() grid.setContentsMargins(0, 0, 0, 0) box.layout().addLayout(grid) self.sample_rows_cb = cb = QCheckBox(checked=self._sample_rows_enabled) spin = QSpinBox(minimum=0, maximum=100, value=self._sample_rows_p, enabled=self._sample_rows_enabled) spin.valueChanged.connect(self.set_sample_rows_p) suffix = QLabel("% of Samples", enabled=self._sample_rows_enabled) cb.toggled.connect(self.set_sample_rows_enabled) cb.toggled.connect(spin.setEnabled) cb.toggled.connect(suffix.setEnabled) grid.addWidget(cb, 0, 0) grid.addWidget(spin, 0, 1) grid.addWidget(suffix, 0, 2) self.sample_cols_cb = cb = QCheckBox(checked=self._sample_cols_enabled) spin = QSpinBox(minimum=0, maximum=100, value=self._sample_cols_p, enabled=self._sample_cols_enabled) spin.valueChanged.connect(self.set_sample_cols_p) suffix = QLabel("% of genes", enabled=self._sample_cols_enabled) cb.toggled.connect(self.set_sample_cols_enabled) cb.toggled.connect(spin.setEnabled) cb.toggled.connect(suffix.setEnabled) grid.addWidget(cb, 1, 0) grid.addWidget(spin, 1, 1) grid.addWidget(suffix, 1, 2) grid.setColumnStretch(3, 10) self.annotation_files_box = box = gui.widgetBox( self.controlArea, "Cell && Gene Annotation Files") form = QFormLayout( formAlignment=Qt.AlignLeft, rowWrapPolicy=QFormLayout.WrapAllRows, ) box.layout().addLayout(form) self.row_annotations_cb = cb = QCheckBox( "Cell annotations", checked=self._row_annotations_enabled) self._row_annotations_w = w = QWidget( enabled=self._row_annotations_enabled) cb.toggled.connect(self.set_row_annotations_enabled) cb.toggled.connect(w.setEnabled) hl = QHBoxLayout() hl.setContentsMargins(0, 0, 0, 0) w.setLayout(hl) self.row_annotations_combo = QComboBox( sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon, minimumContentsLength=18) self.row_annotations_combo.activated.connect(self._invalidate) hl.addWidget(self.row_annotations_combo) hl.addWidget( QPushButton("...", box, autoDefault=False, icon=icon_open_dir, clicked=self.browse_row_annotations)) # hl.addWidget(QPushButton("Reload", box, autoDefault=False, # icon=icon_reload)) form.addRow(cb, w) self.col_annotations_cb = cb = QCheckBox( "Gene annotations", checked=self._col_annotations_enabled) self._col_annotations_w = w = QWidget( enabled=self._col_annotations_enabled) cb.toggled.connect(self.set_col_annotations_enabled) cb.toggled.connect(w.setEnabled) hl = QHBoxLayout() hl.setContentsMargins(0, 0, 0, 0) w.setLayout(hl) self.col_annotations_combo = QComboBox( sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon, minimumContentsLength=18) self.col_annotations_combo.activated.connect(self._invalidate) hl.addWidget(self.col_annotations_combo) hl.addWidget( QPushButton("...", box, autoDefault=False, icon=icon_open_dir, clicked=self.browse_col_annotations)) # hl.addWidget(QPushButton("Reload", box, autoDefault=False, # icon=icon_reload)) form.addRow(cb, w) self.controlArea.layout().addStretch(10) self.load_data_button = button = VariableTextPushButton( "Load data", autoDefault=True, textChoiceList=["Load data", "Reload"]) self.load_data_button.setAutoDefault(True) button.clicked.connect(self.commit, Qt.QueuedConnection) self.controlArea.layout().addWidget(button, alignment=Qt.AlignRight) init_recent_paths_model( self.recent_model, [RecentPath.create(p, []) for p in self._recent], ) init_recent_paths_model( self.row_annotations_combo.model(), [RecentPath.create(p, []) for p in self._recent_row_annotations]) init_recent_paths_model( self.col_annotations_combo.model(), [RecentPath.create(p, []) for p in self._recent_col_annotations]) self._update_summary() self._update_warning() if self._last_path != "" and os.path.exists(self._last_path): self.set_current_path(self._last_path) else: self.recent_combo.setCurrentIndex(-1)
def _set_annotation_files(self): dir_name, basename = os.path.split(self._file_name) basename_no_ext, _ = os.path.splitext(basename) meta_path = os.path.join(dir_name, basename_no_ext + ".meta") if os.path.isfile(meta_path): self.row_annotation_file = RecentPath.create(meta_path, [])
def setup_gui(self): """ Use loader predefined values. If the value is None, set loader's parameter to widget's setting value. """ loader = self._data_loader if loader.header_rows_count is not None: self.set_header_rows_count(loader.header_rows_count, False) else: loader.header_rows_count = self._header_rows_count if loader.header_cols_count is not None: self.set_header_cols_count(loader.header_cols_count, False) else: loader.header_cols_count = self._header_cols_count if loader.transposed is not None: self._cells_in_rows = not loader.transposed else: loader.transposed = not self._cells_in_rows if loader.sample_rows_enabled is not None: self.set_sample_rows_enabled(loader.sample_rows_enabled, False) else: loader.sample_rows_enabled = self._sample_rows_enabled if loader.sample_cols_enabled is not None: self.set_sample_cols_enabled(loader.sample_cols_enabled, False) else: loader.sample_cols_enabled = self._sample_cols_enabled if loader.sample_rows_p is not None: self.set_sample_rows_p(loader.sample_rows_p, False) else: loader.sample_rows_p = self._sample_rows_p if loader.sample_cols_p is not None: self.set_sample_cols_p(loader.sample_cols_p, False) else: loader.sample_cols_p = self._sample_cols_p if loader.row_annotation_file is not None: index = insert_recent_path( self.row_annotations_combo.model(), RecentPath.create(loader.row_annotation_file, [])) self.row_annotations_combo.setCurrentIndex(index) self.set_row_annotations_enabled(loader.row_annotations_enabled, False) else: self.row_annotations_combo.setCurrentIndex(-1) self.set_row_annotations_enabled(False, False) if loader.col_annotation_file is not None: index = insert_recent_path( self.col_annotations_combo.model(), RecentPath.create(loader.col_annotation_file, [])) self.col_annotations_combo.setCurrentIndex(index) self.set_col_annotations_enabled(loader.col_annotations_enabled, False) else: self.col_annotations_combo.setCurrentIndex(-1) self.set_col_annotations_enabled(False, False) self.header_rows_spin.setEnabled(loader.FIXED_FORMAT) self.header_cols_spin.setEnabled(loader.FIXED_FORMAT) self.data_struct_box.setEnabled(loader.FIXED_FORMAT) self.annotation_files_box.setEnabled(loader.ENABLE_ANNOTATIONS)
def add_path(self, filename): recent = RecentPath.create(filename, self._search_paths()) self.recent_paths.append(recent)
def relocate_path(self, path): basedir = self.workflowEnv().get("basedir", None) if not basedir or not path: return path return RecentPath.create(path.abspath, [("basedir", basedir)])
def add_path(self, filename, reader=None): recent = RecentPath.create(filename, self._search_paths()) if reader is not None: recent.file_format = reader.qualified_name() self.recent_paths.append(recent)