def _test_reorder(): frame = wx.GetApp().GetTopWindow() grid = widgetgrid.WidgetGrid(frame) grid.SetGridSize(1, 10) labels = ['col {}'.format(i) for i in range(10)] cells = ['cell {}'.format(i) for i in range(10)] grid.SetColLabels(labels) grid.SetRowLabels(['row']) for i in range(10): grid.SetText(0, i, cells[i]) grid.Refresh() realYield() for i in range(5): neworder = np.array(range(10)) np.random.shuffle(neworder) grid.ReorderColumns(neworder) grid.Refresh() realYield() for i in range(10): assert grid.GetColLabel(i) == labels[neworder[i]] assert grid.GetWidget(0, i).GetLabel() == cells[neworder[i]] labels = [labels[i] for i in neworder] cells = [cells[i] for i in neworder]
def __init__(self, parent, ftpanel, notes='right'): """Create a ``FileListPanel``. :arg parent: ``wx`` parent object :arg ftpanel: The :class:`.FileTreePanel` :arg notes: Location of the *Notes* column - one of: - ``'right'`` - right-most column (default) - ``'left'`` - left-most column, after varying columns The *Notes* column location can be changed later via the :meth:`NotesColumn` method. """ if notes not in ('left', 'right'): raise ValueError('Invalid value for notes: {}'.format(notes)) wx.Panel.__init__(self, parent) self.__ftpanel = ftpanel self.__notes = notes self.__mgr = None self.__sizer = wx.BoxSizer(wx.VERTICAL) self.__grid = wgrid.WidgetGrid( self, style=(wx.HSCROLL | wx.VSCROLL | wgrid.WG_KEY_NAVIGATION | wgrid.WG_SELECTABLE_ROWS | wgrid.WG_DRAGGABLE_COLUMNS)) self.__sizer.Add(self.__grid, flag=wx.EXPAND, proportion=1) self.SetSizer(self.__sizer) self.__grid.Bind(wgrid.EVT_WG_SELECT, self.__onSelect) self.__grid.Bind(wgrid.EVT_WG_REORDER, self.__onReorder)
def _test_create(): frame = wx.GetApp().GetTopWindow() grid = widgetgrid.WidgetGrid(frame) grid.SetGridSize(10, 10) grid.ShowRowLabels() grid.ShowColLabels() for i in range(10): grid.SetRowLabel(i, 'row {}'.format(i + 1)) grid.SetColLabel(i, 'col {}'.format(i + 1)) for i in range(10): for j in range(10): grid.SetText(i, j, 'cell [{}, {}]'.format(i + 1, j + 1)) grid.Refresh() exprowlbls = ['row {}'.format(i + 1) for i in range(10)] expcollbls = ['col {}'.format(i + 1) for i in range(10)] assert grid.GetRowLabels() == exprowlbls assert grid.GetColLabels() == expcollbls for i in range(10): for j in range(10): exp = 'cell [{}, {}]'.format(i + 1, j + 1) assert grid.GetWidget(i, j).GetLabel() == exp
def __init__(self, parent, overlayList, displayCtx, frame, lut): """Create a ``LabelGrid``. :arg parent: The ``wx`` parent object. :arg overlayList: The :class:`.OverlayList`. :arg displayCtx: The :class:`.DisplayContext`. :arg frame: The :class:`.FSLeyesFrame` instance. :arg lut: The :class:`.LookupTable` to be used to colour component tags. """ fslpanel.FSLeyesPanel.__init__(self, parent, overlayList, displayCtx, frame) self.__lut = lut self.__grid = widgetgrid.WidgetGrid( self, style=(wx.VSCROLL | widgetgrid.WG_SELECTABLE_ROWS | widgetgrid.WG_KEY_NAVIGATION)) # The LabelGrid displays one TextTagPanel # for each label that is currently displayed, # as: # # { label_name : TextTagPanel } # # mappings. self.__labelTags = collections.OrderedDict() self.__sizer = wx.BoxSizer(wx.HORIZONTAL) self.__sizer.Add(self.__grid, flag=wx.EXPAND, proportion=1) self.SetSizer(self.__sizer) self.__grid.Bind(widgetgrid.EVT_WG_SELECT, self.__onGridSelect) lut.register(self.name, self.__lutChanged, 'added') lut.register(self.name, self.__lutChanged, 'removed') lut.register(self.name, self.__lutChanged, 'label') self.__overlay = None
def __init__(self, parent, overlayList, displayCtx, frame, lut): """Create a ``ComponentGrid``. :arg parent: The ``wx`` parent object. :arg overlayList: The :class:`.OverlayList`. :arg displayCtx: The :class:`.DisplayContext`. :arg frame: The :class:`.FSLeyesFrame` instance. :arg lut: The :class:`.LookupTable` instance used to colour each label tag. """ fslpanel.FSLeyesPanel.__init__( self, parent, overlayList, displayCtx, frame) self.__lut = lut self.__grid = widgetgrid.WidgetGrid( self, style=(wx.VSCROLL | widgetgrid.WG_SELECTABLE_ROWS | widgetgrid.WG_KEY_NAVIGATION)) self.__grid.ShowRowLabels(False) self.__grid.ShowColLabels(True) self.__sizer = wx.BoxSizer(wx.HORIZONTAL) self.__sizer.Add(self.__grid, flag=wx.EXPAND, proportion=1) self.SetSizer(self.__sizer) self.__grid.Bind(widgetgrid.EVT_WG_SELECT, self.__onGridSelect) lut.register(self.name, self.__lutChanged, 'added') lut.register(self.name, self.__lutChanged, 'removed') lut.register(self.name, self.__lutChanged, 'label') self.__overlay = None self.__volLabels = None
def __init__(self, parent, dcmseries): """Create a ``BrowseDicomPanel``. :arg parent: ``wx`` parent object :arg dcmseries: List of DICOM data series, as returned by the :func:`fsl.data.dicom.scanDir` function. """ wx.Panel.__init__(self, parent) # we assume that this metadata # is the same across all series date = dcmseries[0].get('AcquisitionDateTime', '') dcmdir = dcmseries[0].get('DicomDir', '') patient = dcmseries[0].get('PatientName', '') institution = dcmseries[0].get('InstitutionName', '') try: date = datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f') date = '{:4d}-{:2d}-{:2d}'.format(date.year, date.month, date.day) except ValueError: date = '' self.__dcmdirLabel = wx.StaticText(self) self.__dateLabel = wx.StaticText(self) self.__patientLabel = wx.StaticText(self) self.__institutionLabel = wx.StaticText(self) self.__dcmdir = wx.StaticText(self, style=wx.ST_ELLIPSIZE_START) self.__date = wx.StaticText(self) self.__patient = wx.StaticText(self) self.__institution = wx.StaticText(self) self.__series = wg.WidgetGrid(self, style=0) self.__loadCheckboxes = [wx.CheckBox(self) for s in dcmseries] self.__dcmdirLabel.SetLabel(strings.labels[self, 'dicomdir']) self.__dateLabel.SetLabel(strings.labels[self, 'date']) self.__patientLabel.SetLabel(strings.labels[self, 'patient']) self.__institutionLabel.SetLabel(strings.labels[self, 'institution']) self.__dcmdir.SetLabel(dcmdir) self.__date.SetLabel(date) self.__patient.SetLabel(patient) self.__institution.SetLabel(institution) self.__mainSizer = wx.BoxSizer(wx.VERTICAL) self.__titleSizer = wx.FlexGridSizer(2, 5, 5) self.__titleSizer.AddGrowableCol(1) self.__titleSizer.Add(self.__dcmdirLabel, flag=wx.EXPAND) self.__titleSizer.Add(self.__dcmdir, flag=wx.EXPAND) self.__titleSizer.Add(self.__dateLabel, flag=wx.EXPAND) self.__titleSizer.Add(self.__date, flag=wx.EXPAND) self.__titleSizer.Add(self.__patientLabel, flag=wx.EXPAND) self.__titleSizer.Add(self.__patient, flag=wx.EXPAND) self.__titleSizer.Add(self.__institutionLabel, flag=wx.EXPAND) self.__titleSizer.Add(self.__institution, flag=wx.EXPAND) self.__mainSizer.Add(self.__titleSizer, flag=wx.EXPAND | wx.ALL, border=5) self.__mainSizer.Add(self.__series, flag=wx.EXPAND | wx.ALL, border=5, proportion=1) self.SetSizer(self.__mainSizer) # columns: # SeriesNumber # SeriesDescription # ReconMatrix # Load (checkbox) # TODO For other useful information, # you might need to look in the niftis # set up the grid self.__series.SetGridSize(len(dcmseries), 4, growCols=(0, 1)) self.__series.ShowColLabels() self.__series.SetColLabel(0, strings.labels[self, 'SeriesNumber']) self.__series.SetColLabel(1, strings.labels[self, 'SeriesDescription']) self.__series.SetColLabel(2, strings.labels[self, 'Matrix']) self.__series.SetColLabel(3, strings.labels[self, 'Load']) for i, s in enumerate(dcmseries): num = s['SeriesNumber'] desc = s['SeriesDescription'] size = s['ReconMatrixPE'] self.__series.SetText(i, 0, str(num)) self.__series.SetText(i, 1, desc) self.__series.SetText(i, 2, '{}x{}'.format(size, size)) self.__series.SetWidget(i, 3, self.__loadCheckboxes[i]) self.__series.Refresh()
def __genClusterGrid(self, overlay, featImage, contrast, clusters): """Creates and returns a :class:`.WidgetGrid` which contains the given list of clusters, which are related to the given contrast. .. note:: This method assumes that the given ``overlay`` is an :class:`.Image` which has the same voxel dimensions as, and shares the the same world coordinate system as the ``featImage``. :arg overlay: The overlay for which clusters are currently being displayed. :arg featImage: The :class:`.FEATImage` to which the clusters are related. :arg contrast: The (0-indexed) number of the contrast to which the clusters are related. :arg clusters: A sequence of objects, each representing one cluster. See the :meth:`.FEATImage.clusterResults` method. """ cols = { 'index': 0, 'nvoxels': 1, 'p': 2, 'logp': 3, 'zmax': 4, 'zmaxcoords': 5, 'zcogcoords': 6, 'copemax': 7, 'copemaxcoords': 8, 'copemean': 9 } grid = widgetgrid.WidgetGrid(self) conName = featImage.contrastNames()[contrast] opts = self.displayCtx.getOpts(overlay) # We hide the grid and disable # this panle while the grid is # being created. grid.Hide() self.Disable() grid.SetGridSize(len(clusters), 10) grid.ShowRowLabels(False) grid.ShowColLabels(True) for col, i in cols.items(): grid.SetColLabel(i, strings.labels[self, col]) def makeCoordButton(coords): label = wx.StaticText(grid, label='[{} {} {}]'.format(*coords)) btn = wx.Button(grid, label=six.u('\u2192'), style=wx.BU_EXACTFIT) sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(label, flag=wx.EXPAND, proportion=1) sizer.Add(btn) def onClick(ev): dloc = opts.transformCoords([coords], 'voxel', 'display')[0] self.displayCtx.location = dloc btn.Bind(wx.EVT_BUTTON, onClick) return sizer # Creating all of the widgets could # take a bit of time, so we'll # do it asynchronously via idle.idle # display a message while doing so. status.update(strings.messages[self, 'loadingCluster'].format( contrast + 1, conName), timeout=None) def addCluster(i, clust): if not fwidgets.isalive(grid): return zmaxbtn = makeCoordButton((clust.zmaxx, clust.zmaxy, clust.zmaxz)) zcogbtn = makeCoordButton((clust.zcogx, clust.zcogy, clust.zcogz)) copemaxbtn = makeCoordButton( (clust.copemaxx, clust.copemaxy, clust.copemaxz)) def fmt(v): return '{}'.format(v) grid.SetText(i, cols['index'], fmt(clust.index)) grid.SetText(i, cols['nvoxels'], fmt(clust.nvoxels)) grid.SetText(i, cols['p'], fmt(clust.p)) grid.SetText(i, cols['logp'], fmt(clust.logp)) grid.SetText(i, cols['zmax'], fmt(clust.zmax)) grid.SetWidget(i, cols['zmaxcoords'], zmaxbtn) grid.SetWidget(i, cols['zcogcoords'], zcogbtn) grid.SetText(i, cols['copemax'], fmt(clust.copemax)) grid.SetWidget(i, cols['copemaxcoords'], copemaxbtn) grid.SetText(i, cols['copemean'], fmt(clust.copemean)) # Refresh the grid widget when all # clusters have been added. def onFinish(): if not fwidgets.isalive(grid): return status.update('All clusters loaded.') self.Enable() grid.Show() grid.Refresh() for i, clust in enumerate(clusters): idle.idle(addCluster, i, clust) idle.idle(onFinish) return grid
def __init__(self, parent, knownHosts=None, knownAccounts=None, filterType=None, filters=None): """Create a ``XNATBrowserPanel``. :arg parent: ``wx`` parent object. :arg knownHosts: A sequence of hosts to be used as auto-complete options in the host input field. :arg knownAccounts: A mapping of ``{ host : (username, password) }``, which are used to automatically fill in the login credentials when a particular host name is entered. :arg filterType: How the filter patterns should be applied - either ``'regexp'`` for regular expressions, or ``'glob'`` for shell-style wildcard patterns. Defaults to ``'regexp'``. :arg filters: Mapping containing initial filter values. Must be of the form ``{ level : pattern }``, where ``level`` is the name of an XNAT hierarchy level (e.g. ``'subject'``, ``'file'``, etc.). """ if knownHosts is None: knownHosts = [] if knownAccounts is None: knownAccounts = {} if filterType is None: filterType = 'regexp' if filters is None: filters = {} if filterType not in ('regexp', 'glob'): raise ValueError('Unrecognised value for filterType: ' '{}. May be one of \'regexp\' or ' '\'glob\''.format(filterType)) # store hosts without # the http[s]:// prefix knownHosts = [h.strip('https://') for h in knownHosts] knownAccounts = {h.strip('https://') : (u, p) for h, (u, p) in knownAccounts.items()} knownHosts += [h for h in knownAccounts.keys() if h not in knownHosts] wx.Panel.__init__(self, parent) self.__knownHosts = knownHosts self.__knownAccounts = knownAccounts self.__filterType = filterType self.__session = None self.__filters = collections.OrderedDict([ ('subject', ''), ('experiment', ''), ('file', ''), ]) self.__filters.update(**filters) self.__host = at.AutoTextCtrl(self) self.__username = pt.PlaceholderTextCtrl(self, placeholder='username') self.__password = pt.PlaceholderTextCtrl(self, placeholder='password', style=wx.TE_PASSWORD) self.__connect = wx.Button(self) self.__status = wx.StaticText(self) self.__project = wx.Choice(self) self.__refresh = wx.Button(self) self.__filter = wx.Choice(self) self.__filterText = pt.PlaceholderTextCtrl(self, placeholder=filterType, style=wx.TE_PROCESS_ENTER) self.__splitter = wx.SplitterWindow(self, style=(wx.SP_LIVE_UPDATE | wx.SP_BORDER)) self.__info = wgrid.WidgetGrid(self.__splitter) self.__browser = wx.TreeCtrl(self.__splitter, style=(wx.TR_MULTIPLE | wx.TR_NO_LINES | wx.TR_HAS_BUTTONS | wx.TR_TWIST_BUTTONS)) self.__splitter.SetMinimumPaneSize(50) self.__splitter.SplitHorizontally(self.__info, self.__browser) self.__splitter.SetSashPosition(50) self.__splitter.SetSashGravity(0.2) images = [icons.loadBitmap(icons.FILE_ICON), icons.loadBitmap(icons.FOLDER_UNLOADED_ICON), icons.loadBitmap(icons.FOLDER_LOADED_ICON)] self.__fileImageId = 0 self.__unloadedFolderImageId = 1 self.__loadedFolderImageId = 2 imageList = wx.ImageList(16, 16) for i in images: imageList.Add(images[0]) imageList.Add(images[1]) imageList.Add(images[2]) self.__browser.AssignImageList(imageList) self.__filter.SetItems([LABELS[f] for f in self.__filters.keys()]) self.__filter.SetSelection(0) self.__hostLabel = wx.StaticText(self) self.__usernameLabel = wx.StaticText(self) self.__passwordLabel = wx.StaticText(self) self.__projectLabel = wx.StaticText(self) self.__filterLabel = wx.StaticText(self) self.__status.SetFont(self.__status.GetFont().Larger().Larger()) self.__info.SetColours(border=self.__info._defaultEvenColour) self.__host .AutoComplete(knownHosts) self.__hostLabel .SetLabel(LABELS['host']) self.__usernameLabel.SetLabel(LABELS['username']) self.__passwordLabel.SetLabel(LABELS['password']) self.__connect .SetLabel(LABELS['connect']) self.__projectLabel .SetLabel(LABELS['project']) self.__filterLabel .SetLabel(LABELS['filter']) self.__refresh .SetLabel(LABELS['refresh']) filterTooltip = wx.ToolTip(TOOLTIPS['filter.{}'.format(filterType)]) self.__filterLabel.SetToolTip(filterTooltip) self.__filter .SetToolTip(filterTooltip) self.__filterText .SetToolTip(filterTooltip) self.__loginSizer = wx.BoxSizer(wx.HORIZONTAL) self.__filterSizer = wx.BoxSizer(wx.HORIZONTAL) self.__mainSizer = wx.BoxSizer(wx.VERTICAL) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__hostLabel) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__host, proportion=1) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__usernameLabel) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__username, proportion=1) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__passwordLabel) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__password, proportion=1) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__connect) self.__loginSizer.Add((5, 1)) self.__loginSizer.Add(self.__status) self.__loginSizer.Add((5, 1)) self.__filterSizer.Add((5, 1)) self.__filterSizer.Add(self.__projectLabel) self.__filterSizer.Add((5, 1)) self.__filterSizer.Add(self.__project, proportion=1) self.__filterSizer.Add((5, 1)) self.__filterSizer.Add(self.__filterLabel) self.__filterSizer.Add((5, 1)) self.__filterSizer.Add(self.__filter) self.__filterSizer.Add((5, 1)) self.__filterSizer.Add(self.__filterText, proportion=1) self.__filterSizer.Add((5, 1)) self.__filterSizer.Add(self.__refresh) self.__filterSizer.Add((5, 1)) self.__mainSizer.Add(self.__loginSizer, flag=wx.EXPAND) self.__mainSizer.Add((1, 10)) self.__mainSizer.Add(self.__filterSizer, flag=wx.EXPAND) self.__mainSizer.Add((1, 10)) self.__mainSizer.Add(self.__splitter, flag=wx.EXPAND, proportion=1) self.SetSizer(self.__mainSizer) self.__host .Bind(at.EVT_ATC_TEXT_ENTER, self.__onHost) self.__connect.Bind(wx.EVT_BUTTON, self.__onConnect) self.__project.Bind(wx.EVT_CHOICE, self.__onProject) self.__refresh.Bind(wx.EVT_BUTTON, self.__onRefresh) self.__filter .Bind(wx.EVT_CHOICE, self.__onFilter) self.__browser.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.__onTreeActivate) self.__browser.Bind(wx.EVT_TREE_SEL_CHANGED, self.__onTreeSelect) self.__filterText.Bind(wx.EVT_TEXT_ENTER, self.__onFilterText) self.__updateFilter() self.EndSession()
def _test_reorder_events_draglimit(): realYield() frame = wx.GetApp().GetTopWindow() frame.SetSize((800, 600)) sim = wx.UIActionSimulator() grid = widgetgrid.WidgetGrid(frame, style=widgetgrid.WG_DRAGGABLE_COLUMNS) sizer = wx.BoxSizer(wx.VERTICAL) frame.SetSizer(sizer) sizer.Add(grid, flag=wx.EXPAND, proportion=1) grid.ShowColLabels() grid.SetGridSize(1, 5) grid.SetDragLimit(2) labels = ['col {}'.format(i) for i in range(5)] cells = ['cell {}'.format(i) for i in range(5)] for i in range(5): grid.SetColLabel(i, labels[i]) for i in range(5): grid.SetText(0, i, cells[i]) grid.Refresh() frame.Layout() # (clicked column, drop column, drop pos, expected order) tests = [ (0, 1, 0.75, [1, 0, 2, 3, 4]), (1, 2, 0.75, [0, 2, 1, 3, 4]), (1, 0, 0.25, [1, 0, 2, 3, 4]), (2, 1, 0.25, [0, 2, 1, 3, 4]), # drop is past drag limit -> clamp (0, 3, 0.75, [1, 2, 0, 3, 4]), (0, 4, 0.75, [1, 2, 0, 3, 4]), # past drag limit -> no-ops (3, 1, 0.25, [0, 1, 2, 3, 4]), (3, 4, 0.75, [0, 1, 2, 3, 4]), (4, 3, 0.25, [0, 1, 2, 3, 4]), ] realYield() for clickcol, dropcol, droppos, exporder in tests: fakestate = FakeMouseState() with mock.patch('wx.GetMouseState', return_value=fakestate): cwidget = grid.colLabels[clickcol].GetParent() dwidget = grid.colLabels[dropcol].GetParent() ev = FakeEV(cwidget) grid._WidgetGrid__onColumnLabelMouseDown(ev) realYield() fakestate.pos = wx.Point(*cxy(dwidget, (droppos, 0.5))) with mock.patch('wx.FindWindowAtPointer', return_value=[dwidget]): grid._WidgetGrid__onColumnLabelMouseDrag(ev) realYield() ev.evo = dwidget grid._WidgetGrid__onColumnLabelMouseUp(ev) realYield() explabels = [labels[i] for i in exporder] gotlabels = grid.GetColLabels() assert explabels == gotlabels labels = gotlabels