コード例 #1
0
    def __init__(self, treeView):
        QtWidgets.QWidget.__init__(self)
        self._treeView = treeView
        self._menu = QtWidgets.QMenu(self)
        d = PathStr.getcwd()
        iconpath = os.path.join(d, 'media', 'icons', 'approve.svg')
        self._actionStart = QtWidgets.QAction(QtGui.QIcon(iconpath),
                                              'Start', self._treeView,
                                              triggered=self._treeView.openProject)

        iconpath = os.path.join(d, 'media', 'icons', 'delete.svg')
        delete = QtWidgets.QAction(QtGui.QIcon(iconpath),
                                   'Delete', self._treeView,
                                   triggered=self._treeView.deleteSelected)

        iconpath = os.path.join(d, 'media', 'icons', 'rename.svg')
        rename = QtWidgets.QAction(QtGui.QIcon(iconpath),
                                   'Rename', self._treeView,
                                   triggered=self._treeView.editSelected)

        iconpath = os.path.join(d, 'media', 'icons', 'new.svg')
        newDir = QtWidgets.QAction(QtGui.QIcon(iconpath),
                                   'New Directory', self._treeView,
                                   triggered=self._treeView.newDirInSelected)

        iconpath = os.path.join(d, 'media', 'icons', 'findReplace.svg')
        self._editStartScript = QtWidgets.QAction(QtGui.QIcon(iconpath),
                                                  'Edit start script', self._treeView,
                                                  triggered=self._treeView.editStartScriptInSelected)

        iconpath = os.path.join(d, 'media', 'icons', 'bug.png')
        self._actionInDebugMode = QtWidgets.QAction(QtGui.QIcon(iconpath),
                                                    'Run in debug mode', self._treeView,
                                                    triggered=self._treeView.runInDebugMode)

        self._menu.addAction(self._actionStart)
        self._menu.addAction(rename)
        self._menu.addAction(newDir)
        self._menu.addAction(self._editStartScript)
        self._menu.addAction(delete)
        self._menu.addAction(self._actionInDebugMode)
コード例 #2
0
class ImageWidget(DisplayWidget, ImageView, PyqtgraphgDisplayBase):
    '''
    A pyqtgraph.ImageView with methods to add/move/remove images
    as layer or colour-layer
    '''
    dimensions = (3, 4)
    icon = PathStr.getcwd('dataArtist').join('media', 'icons', 'image.svg')
    sigOverlayAdded = QtCore.Signal(object, object, object)  # item, name, tip
    sigOverlayRemoved = QtCore.Signal(object)  # item

    shows_one_layer_at_a_time = True

    def __init__(self, display, axes, data=None, names=None, **kwargs):
        for a in axes:
            a.setPen()  # update colour theme

        ImageView.__init__(
            self, view=pg.PlotItem(
                axisItems={
                    'bottom': axes[0],
                    'left': axes[1]})
        )
        PyqtgraphgDisplayBase.__init__(self)
        DisplayWidget.__init__(self, **kwargs)

        self.display = display
        self.moveLayerToNewImage = None
        self.cItems = OrderedDict()  # colorlayerItems

        self.sigTimeChanged.connect(self.display.highlightLayer)

        # for unified access within different widgets:
        self.item = self.imageItem
        self.setTitle = self.view.setTitle

        self._firstTime = True
        self._changed = False
        self._timeline_visible = True
        self._image_redefined = False
        self._moved_layer = None
        self._set_kwargs = {}

        self.opts['discreteTimeLine'] = True

        # TODO: better would be to init imageView with given histrogramAxis
        #      ... but this is easier:
        axes[2].sigLabelChanged.connect(self.setHistogramLabel)
        self.setHistogramLabel(axes[2].labelText)
        axes[2].sigRangeChanged.connect(self.ui.histogram.axis.setRange)
        axes[2].sigFontSizeChanged.connect(self._setHistogramFontSize)

        # hide buttons
        self.ui.roiBtn.hide()
        self.ui.menuBtn.hide()
        # fixed height for time axis:
        self.ui.splitter.setSizes([self.height() - 35, 35])
        self.ui.splitter.setStretchFactor(0, 1)
        # Remove ROI plot:
        self.ui.roiPlot.setMouseEnabled(False, False)
        self.ui.roiPlot.hide()

        # -------------------
        # Context menu over colorbar histogram:
        vb = self.ui.histogram.vb
        menu = vb.menu
        # remove 'Export...' menu:
        vb.raiseContextMenu = self._cbar_raiseContextMenu
        # remove mouse mode
        menu.removeAction(menu.leftMenu.menuAction())
        # remove redundsant menus:
        menu.removeAction(
            next(a for a in menu.actions() if a.text() == 'X Axis'))
#         menu.removeAction(
#             next(a for a in menu.actions() if 'Export' in a.text()))
        # y-Axis menu
        yAxisAction = next(a for a in menu.actions() if a.text() == 'Y Axis')
        yAxisAction.setText('Scale')
        # connect min-max edit with cbar intensity range change:
        menu.ctrl[-1].minText.editingFinished.connect(self._cbar_updateRange)
        menu.ctrl[-1].maxText.editingFinished.connect(self._cbar_updateRange)
        # add cbar fit:
        menu.addAction('Fit').triggered.connect(self._cbar_fit)
        # -------------------

    def _cbar_updateRange(self):
        c = self.ui.histogram.vb.menu.ctrl[-1]
        mn = float(c.minText.text())
        mx = float(c.maxText.text())
        self.ui.histogram.item.setLevels(mn, mx)

    def _cbar_fit(self):
        img = self.image[self.currentIndex]
        r = scaleSignalCutParams(img, 0.01)
        self.ui.histogram.setLevels(*r)

    def _cbar_raiseContextMenu(self, ev):
        vb = self.ui.histogram.vb
        menu = vb.getMenu(ev)
        menu.popup(ev.screenPos().toPoint())

    def setOpts(self, **opts):
        self.opts.update(opts)

    @staticmethod
    def getNLayers(data):
        if data is None:
            return 0
        s = data.shape
        l = data.ndim
        if l == 2:
            return 1
        if l == 3:
            if s[-1] in (3, 4):
                return 1
            return s[0]
        if l == 4:
            if s[-1] in (3, 4):
                return s[0]
        return 0

    def close(self):
        self.sigTimeChanged.disconnect(self.display.highlightLayer)

        self.clear()  # free memory
        try:
            ImageView.close(self)
        except TypeError:
            pass

    def roiClicked(self):
        '''not used'''
        pass

    def roiChanged(self):
        '''not used'''
        pass

    def saveState(self):
        state = DisplayWidget.saveState(self)
        state['view'] = self.view.vb.getState()
        state['histogram'] = self.ui.histogram.vb.getState()
        state['histoRegion'] = self.ui.histogram.getLevels()
        state['colorbar'] = self.ui.histogram.gradient.saveState()
        state['currentIndex'] = self.currentIndex
        state['image'] = self.image
        return state

    def restoreState(self, state):
        self.view.vb.setState(state['view'])
        self.ui.histogram.vb.setState(state['histogram'])
        self.ui.histogram.setLevels(*state['histoRegion'])
        self.ui.histogram.gradient.restoreState(state['colorbar'])
        img = state['image']
        if img is not None:
            self.setImage(img, autoRange=False, autoLevels=False,
                          autoHistogramRange=False)
        try:
            self.setCurrentIndex(state['currentIndex'])
        except AttributeError:
            # cannot set index, because has no layers
            pass
        DisplayWidget.restoreState(self, state)

    def showTimeline(self, show=True):
        self._timeline_visible = show
        if show and len(self.image) > 1:
            self.ui.roiPlot.show()
        else:
            self.ui.roiPlot.hide()

    def setColorLayer(self, layer, **kwargs):
        '''
        same as addColorLayer, but replaces citem, if existent
        '''
        name = kwargs.get('name', None)
        if name:
            item = self.cItems.get(name, None)
            if item:
                return item.setLayer(layer)
        return self.addColorLayer(layer, **kwargs)

    def addColorLayer(self, layer=None, name='Unnamed', tip='',
                      color=None, alpha=0.5):
        '''
        add a [layer], a np.array (2d or 3d), as colour overlay to the image
        '''
        if layer is None:
            s = self.image.shape
            if len(s) == 4:  # multi layer color image
                s = s[1:-1]
            elif len(s) == 3:
                if s[-1] == 3:  # single layer color image
                    s = s[:-1]
                else:  # multi layer grey image
                    s = s[1:]
            layer = np.zeros(shape=s)

        if isColor(layer):
            layer = toGray(layer)

        if color is None:
            # set colour as function of the number of colorItems:
            color = pg.intColor(len(self.cItems)).rgb()

        cItem = ColorLayerItem(layer,
                               imageWidget=self,
                               color=color,
                               alpha=alpha
                               )
        name = incrementName(list(self.cItems.keys()), name)
        self.cItems[name] = cItem
        self.view.addItem(cItem)
        self.sigOverlayAdded.emit(cItem, name, tip)
        return cItem

    def removeColorLayer(self, nameOrItem):
        if isinstance(nameOrItem, ColorLayerItem):
            for name, item in self.cItems.items():
                if item == nameOrItem:
                    break
        else:
            name = nameOrItem
        item = self.cItems.pop(name)
        self.view.removeItem(item)
        self.sigOverlayRemoved.emit(item)
        del item

    def _setHistogramFontSize(self, ptSize):
        '''
        set font size of the histogram and change the size of the
        viewBox that contain the image and the histogram accordingly
        '''
        vb = self.ui.histogram.vb
        if not hasattr(self, '_initHistWidth'):
            w = self._initHistWidth = vb.width()
        else:
            w = self._initHistWidth
        vb.setFixedWidth(w * (9.0 / ptSize))
        self.ui.histogram.axis.setFontSize(ptSize)
        self.ui.histogram.axis.update()

    def insertLayer(self, index, name=None, data=None):
        '''
        insert a new image as layer
        ...add new / override existing layer
        ...show dialog when data.shape != self.image.shape
        '''
        if data is not None:
            try:
                self.image = np.insert(self.image, index, data, axis=0)

            except IndexError:
                index = -1
                self.image = np.insert(self.image, index, data, axis=0)

            except (ValueError, MemoryError):
                if index == 0 and len(self.image) == 1:
                    # replace, if only has one layer
                    self.image = np.expand_dims(data, axis=0)
                else:
                    if isinstance(data, list):
                        data = data[0]

                    s1 = self.image[0].shape
                    s2 = data.shape
                    # LAYER COLOR IS DIFFERENT:
                    c1 = isColor(self.image[0])
                    c2 = isColor(data)
                    if c1 and not c2:
                        data = toColor(data)
                        s2 = data.shape
                    elif not c1 and c2:
                        self.image = toColor(self.image)
                        s1 = self.image[0].shape
                    if s1 != s2:
                        if isRot90(s1, s2):
                            print('Image is rotated 90DEG.')
                            data = rot90(data)
                        else:
                            # NEW LAYER SHAPE DOESNT FIT EXISTING:
                            ###show DIALOG#####
                            d = DifferentShapeDialog(name, s1, s2)
                            d.exec_()

                            r = d.opt
                            if r == d.optNewDisplay:
                                self.moveLayerToNewImage = index
                                return
                            elif r == d.optCut:
                                data = data[0:s1[0], 0:s1[1]]
                                if data.shape != s1:
                                    d = np.zeros(s1)
                                    d[0:s2[0], 0:s2[1]] = data
                                    data = d
                            elif r == d.optResize:
                                data = cv2.resize(data, (s1[1], s1[0]))

                            elif r == d.optWarp:
                                data = PerspectiveImageStitching(
                                    self.image[-1]).fitImg(data)

                    self.image = np.insert(self.image, index, data, axis=0)

            self.currentIndex = index
            self.setImage(self.image)
            return self.image[index]

    def insertMovedLayer(self, index):
        self.insertLayer(index, data=self._moved_layer)

    def addLayer(self, name=None, data=None, index=None):
        '''
        add a new image as layer the the and of the image stack
        '''
        if self.image is not None:
            if index is None:
                index = len(self.image)
            self.insertLayer(index, data=data)
        else:
            self.update(data)
        self.updateView()
        if self.image is not None:
            self.setCurrentIndex(len(self.image))

    def removeLayer(self, index, toMove=False):
        if self.moveLayerToNewImage is None or self.moveLayerToNewImage != index:
            if toMove:
                if self.image is not None:
                    self._moved_layer = self.image[index]
                else:
                    self._moved_layer = None
            self.image = np.delete(self.image, index, axis=0)
            s = self.image.shape[0]
            if s == 0:
                self.image = None
                self.imageDisp = None
                self.item.clear()
            else:
                # TODO: has last index, if addWidget was called before
                    # therefore index cannot be preserved when layers are
                    # limited
                i = self.currentIndex
                if index != 0 and i == index:
                    i -= 1
                self.setImage(self.image)
                self.setCurrentIndex(i)
        # reset:
        self.moveLayerToNewImage = None

    def clear(self):
        self.setImage(np.zeros((1, 3, 3)))
        self.image = None
        for name in self.cItems:
            self.removeColorLayer(name)

    def getData(self, index=None):
        '''
        return all image layers or one specified by index
        '''
        if self.image is None:
            return None
        if index is not None:
            return self.image[index]
        return self.image

    def update(self, data=None, index=None, label=None, **kwargs):
        '''
        update either the full image or an image layer
        '''
        if data is not None:
            data = np.asarray(data)
            if index is not None and self.image is not None:
                try:
                    self.image[index] = data
                except (ValueError, IndexError):
                    self.insertLayer(index, name=label, data=data)
            else:
                # set all layers
                if (data.ndim == 2  # single grayscale
                        or data.ndim == 3
                        and data.shape[2] in (3, 4)):  # single color
                    data = np.expand_dims(data, axis=0)
                if self.image is None or self.image.shape != data.shape:
                    self._image_redefined = True
                self.image = data
        self._set_kwargs = kwargs
        self._set_index = index
        self._changed = True

    def updateView(self, force=False):
        '''
        update the visual representation
        '''
        if self.image is not None and (force or self._changed):
            if self._image_redefined or self._firstTime:
                self.setImage(self.image, **self._set_kwargs)
                self._firstTime = False
                self._image_redefined = False

            elif (force or self._set_index is None or
                  self._set_index == self.currentIndex):
                # needed by ImageView to set histogram levels
                self.imageDisp = None
                self.updateImage(**self._set_kwargs)
                if self.opts['autoLevels']:
                    self.autoLevels()
            self._changed = False

    def updateImage(self, autoHistogramRange=None, levels=None):
        '''
        overwrite original method to hide timeline when
        3d image has only one layer
        '''
        # Redraw image on screen
        if self.image is None:
            return

        if autoHistogramRange is None:
            autoHistogramRange = self.opts['autoHistogramRange']

        if levels is not None:
            self.setLevels(*levels)

        image = self.getProcessedImage()

        if autoHistogramRange:
            if np.isinf(self.levelMax):
                # otherwise crashes when loading images containing inf
                self.levelMax = self.quickMinMax(image[np.isfinite(image)])[1]
            self.ui.histogram.setHistogramRange(self.levelMin, self.levelMax)

        if self.axes['t'] is not None:
            # show/hide timeline:
            self.ui.roiPlot.setVisible(
                self.image.shape[0] > 1 and self._timeline_visible)
            image = image[self.currentIndex]

        # ensure initial right scaling (not done when image is [0...1]
        # TODO: fix the origin bug
        if image.dtype == bool:
            return self.imageItem.updateImage(image, levels=(0., 1.))

        # else: #TODO: dA crashes with self.levelMin == self.levelMax
        elif self.levelMin != self.levelMax:
            self.imageItem.updateImage(image)
コード例 #3
0
    def __init__(self,
                 title='PYZ-Launcher',
                 icon=None,
                 start_script=None,
                 left_header=None,
                 right_header=None,
                 file_type='pyz'
                 ):
        self.dialogs = Dialogs()

        _path = PathStr.getcwd()
        _default_text_color = '#3c3c3c'

        if icon is None:
            icon = os.path.join(_path, 'media', 'launcher_logo.svg')
        if start_script is None:
            start_script = os.path.join(_path, 'test_session.py')
        if left_header is None:
            _description = "<a href=%s style='color: %s'>%s</a>" % (
                appbase.__url__, _default_text_color, appbase.__description__)

            left_header = """<b>%s</b><br>
                version&nbsp;&nbsp;
                <a href=%s style='color: %s'>%s</a><br>
                autor&nbsp;&nbsp;&nbsp;&nbsp;
                    <a href=mailto:%s style='color: %s'>%s</a> """ % (  # text-decoration:underline
                _description,
                os.path.join(_path, 'media', 'recent_changes.txt'),
                _default_text_color,
                appbase.__version__,
                appbase.__email__,
                _default_text_color,
                appbase.__author__
            )
        if right_header is None:
            # if no header is given, list all pdfs in folder media as link
            d = _path
            right_header = ''
            for f in os.listdir(os.path.join(d, 'media')):
                if f.endswith('.pdf'):
                    _guidePath = os.path.join(d, 'media', f)
                    right_header += "<a href=%s style='color: %s'>%s</a><br>" % (
                        _guidePath, _default_text_color, f[:-4])
            right_header = right_header[:-4]

        QtWidgets.QMainWindow.__init__(self)

        self._start_script = start_script
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(icon))
        self.resize(900, 500)
        # BASE STRUTURE
        area = QtWidgets.QWidget()
        self.setCentralWidget(area)
        layout = QtWidgets.QVBoxLayout()
        area.setLayout(layout)
        #header = QtWidgets.QHBoxLayout()
        # layout.addLayout(header)
        # grab the default text color of a qlabel to color all links from blue to it:
        # LEFT TEXT
        info = QtWidgets.QLabel(left_header)
        info.setOpenExternalLinks(True)
        # LOGO
        header = QtWidgets.QWidget()
        header.setFixedHeight(70)
        headerlayout = QtWidgets.QHBoxLayout()
        header.setLayout(headerlayout)
        logo = QtSvg.QSvgWidget(icon)
        logo.setFixedWidth(50)
        logo.setFixedHeight(50)
        headerlayout.addWidget(logo)
        headerlayout.addWidget(info)
        layout.addWidget(header)
        # RIGHT_HEADER
        userGuide = QtWidgets.QLabel(right_header)
        userGuide.setOpenExternalLinks(True)
        userGuide.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignRight)
        headerlayout.addWidget(userGuide)
        # ROOT-PATH OF THE SESSIONS
        rootLayout = QtWidgets.QHBoxLayout()
        rootFrame = QtWidgets.QFrame()
        rootFrame.setFrameStyle(
            QtWidgets.QFrame.StyledPanel | QtWidgets.QFrame.Plain)
        rootFrame.setFixedHeight(45)
        rootFrame.setLineWidth(0)
        rootFrame.setLayout(rootLayout)
        layout.addWidget(rootFrame)
        self.rootDir = QtWidgets.QLabel()
        self.rootDir.setAutoFillBackground(True)
        self.rootDir.setStyleSheet("QLabel { background-color: white; }")

        # FILE-BROWSER
        self.treeView = _TreeView()

        self.fileSystemModel = _FileSystemModel(self.treeView, file_type)
        self.fileSystemModel.setNameFilters(['*.%s' % file_type])
        self.fileSystemModel.setNameFilterDisables(False)
        self.treeView.setModel(self.fileSystemModel)

        treelayout = QtWidgets.QHBoxLayout()
        splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation(1))

        self.fileInfo = _PyzInfo(splitter, self.fileSystemModel, self.treeView)
        self.treeView.clicked.connect(self.fileInfo.update)

        splitter.addWidget(self.treeView)
        splitter.addWidget(self.fileInfo)
        treelayout.addWidget(splitter)

        layout.addLayout(treelayout)

        # get last root-path
        self._path = PathStr('')
        if CONFIG_FILE:
            try:
                self._path = PathStr(
                    open(
                        CONFIG_FILE,
                        'r').read().decode('unicode-escape'))
            except IOError:
                pass  # file not existant
        if not self._path or not self._path.exists():
            msgBox = QtWidgets.QMessageBox()
            msgBox.setText("Please choose your projectDirectory.")
            msgBox.exec_()
            self._changeRootDir()
        self.treeView.setPath(self._path)
        abspath = os.path.abspath(self._path)
        self.rootDir.setText(abspath)
        rootLayout.addWidget(self.rootDir)
        # GO UPWARDS ROOT-PATH BUTTON
        btnUpRootDir = QtWidgets.QPushButton('up')
        btnUpRootDir.clicked.connect(self._goUpRootDir)
        rootLayout.addWidget(btnUpRootDir)
        # DEFINE CURRENT DIR AS ROOT-PATH
        btnDefineRootDir = QtWidgets.QPushButton('set')
        btnDefineRootDir.clicked.connect(self._defineRootDir)
        rootLayout.addWidget(btnDefineRootDir)
        # SELECT ROOT-PATH BUTTON
        buttonRootDir = QtWidgets.QPushButton('select')
        buttonRootDir.clicked.connect(self._changeRootDir)
        rootLayout.addWidget(buttonRootDir)
        # NEW-BUTTON
        if self._start_script:
            newButton = QtWidgets.QPushButton('NEW')
            newButton.clicked.connect(self._openNew)
            layout.addWidget(newButton)
コード例 #4
0
'''
Count coded lines of all projects
'''
from fancytools.utils.countLines import countLines
from fancytools.os.PathStr import PathStr

d = PathStr.getcwd().dirname()

countLines(
    [
        d.join('dataArtist'),
        d.join('fancyTools'),
        d.join('fancyWidgets'),
        d.join('appBase'),
        d.join('imgprocessor'),
        #d.join('pvimgprocessor'),
        d.join('interactiveTutorial'),
        d.join('headerSetter')
    ],
    exclude_folders_containing=("DUMP", 'dist', 'dev', 'build', 'fancytools3'),
    exclude_blank_lines=True,
    exclude_commented_lines=True,
    count_only_py_files=True)
コード例 #5
0
ファイル: ImageWidget.py プロジェクト: VaporC/dataArtist
class ImageWidget(DisplayWidget, ImageView, PyqtgraphgDisplayBase):
    '''
    A pyqtgraph.ImageView with methods to add/move/remove images 
    as layer or colour-layer
    '''
    dimensions = (3, 4)
    icon = PathStr.getcwd('dataArtist').join('media', 'icons', 'image.svg')
    sigOverlayAdded = QtCore.pyqtSignal(object, object,
                                        object)  #item, name, tip
    sigOverlayRemoved = QtCore.pyqtSignal(object)  #item

    shows_one_layer_at_a_time = True

    def __init__(self, display, axes, data=None, names=None, **kwargs):
        for a in axes:
            a.setPen()  # update colour theme

        ImageView.__init__(self,
                           view=pg.PlotItem(axisItems={
                               'bottom': axes[0],
                               'left': axes[1]
                           }))
        PyqtgraphgDisplayBase.__init__(self)
        DisplayWidget.__init__(self, **kwargs)

        self.display = display
        self.moveLayerToNewImage = None
        self.cItems = OrderedDict()  #colorlayerItems

        #for unified access within different widgets:
        self.item = self.imageItem
        self.setTitle = self.view.setTitle

        self._firstTime = True
        self._changed = False
        self._timeline_visible = True
        self._image_redefined = False
        self._moved_layer = None
        self._set_kwargs = {}

        self.setOpts(discreteTimeSteps=True)

        #make splitter an unchangeable small grey line:
        s = self.ui.splitter
        s.handle(1).setEnabled(False)
        s.setStyleSheet("QSplitter::handle{background-color: grey}")
        s.setHandleWidth(2)

        #TODO: better would be to init imageView with given histrogramAxis
        #      ... but this is easier:
        axes[2].sigLabelChanged.connect(self.setHistogramLabel)
        self.setHistogramLabel(axes[2].labelText)
        axes[2].sigRangeChanged.connect(self.ui.histogram.axis.setRange)
        axes[2].sigFontSizeChanged.connect(self._setHistogramFontSize)

        #hide buttons
        self.ui.roiBtn.hide()
        self.ui.normBtn.hide()
        #fixed height for time axis:
        self.ui.splitter.setSizes([self.height() - 35, 35])
        self.ui.splitter.setStretchFactor(0, 1)
        #Remove ROI plot:
        self.ui.roiPlot.setMouseEnabled(False, False)
        self.ui.roiPlot.hide()

        if data is not None:
            self.update(data)
            self.updateView()

    @staticmethod
    def getNLayers(data):
        s = data.shape
        l = data.ndim
        if l == 2:
            return 1
        if l == 3:
            if s[-1] in (3, 4):
                return 1
        if l == 4:
            if s[-1] in (3, 4):
                return s[0]
        return 0

    def close(self):
        self.clear()  #free memory
        try:
            ImageView.close(self)
        except TypeError:
            pass

    def roiClicked(self):
        '''not used'''
        pass

    def roiChanged(self):
        '''not used'''
        pass

    def saveState(self):
        state = DisplayWidget.saveState(self)
        state['view'] = self.view.vb.getState()
        state['histogram'] = self.ui.histogram.vb.getState()
        state['histoRegion'] = self.ui.histogram.getLevels()
        state['colorbar'] = self.ui.histogram.gradient.saveState()
        state['image'] = self.image
        return state

    def restoreState(self, state):
        self.view.vb.setState(state['view'])
        self.ui.histogram.vb.setState(state['histogram'])
        self.ui.histogram.setLevels(*state['histoRegion'])
        self.ui.histogram.gradient.restoreState(state['colorbar'])
        img = state['image']
        if img is not None:
            self.setImage(img,
                          autoRange=False,
                          autoLevels=False,
                          autoHistogramRange=False)
        DisplayWidget.restoreState(self, state)

    def showTimeline(self, show=True):
        self._timeline_visible = show
        if show and len(self.image) > 1:
            self.ui.roiPlot.show()
        else:
            self.ui.roiPlot.hide()

    def setColorLayer(self, layer, **kwargs):
        '''
        same as addColorLayer, but replaces citem, if existent
        '''
        name = kwargs.get('name', None)
        if name:
            item = self.cItems.get(name, None)
            if item:
                return item.setLayer(layer)
        return self.addColorLayer(layer, **kwargs)

    def addColorLayer(self,
                      layer=None,
                      name='Unnamed',
                      tip='',
                      color=None,
                      alpha=0.5):
        '''
        add a [layer], a np.array (2d or 3d), as colour overlay to the image
        '''
        if layer is None:
            s = self.image.shape
            if len(s) == 4:  # multi layer color image
                s = s[1:-1]
            elif len(s) == 3:
                if s[-1] == 3:  # single layer color image
                    s = s[:-1]
                else:  #multi layer grey image
                    s = s[1:]
            layer = np.zeros(shape=s)

        if isColor(layer):
            layer = toGray(layer)

        if color is None:
            #set colour as function of the number of colorItems:
            color = pg.intColor(len(self.cItems)).rgb()

        cItem = ColorLayerItem(layer,
                               imageWidget=self,
                               color=color,
                               alpha=alpha)
        name = incrementName(self.cItems.keys(), name)
        self.cItems[name] = cItem
        self.view.addItem(cItem)
        self.sigOverlayAdded.emit(cItem, name, tip)
        return cItem

    def removeColorLayer(self, nameOrItem):
        if isinstance(nameOrItem, ColorLayerItem):
            for name, item in self.cItems.iteritems():
                if item == nameOrItem:
                    break
        else:
            name = nameOrItem
        item = self.cItems.pop(name)
        self.view.removeItem(item)
        self.sigOverlayRemoved.emit(item)
        del item

    def _setHistogramFontSize(self, ptSize):
        '''
        set font size of the histogram and change the size of the 
        viewBox that contain the image and the histogram accordingly 
        '''
        vb = self.ui.histogram.vb
        vb.setFixedWidth(vb.width() * (9.0 / ptSize))
        self.ui.histogram.axis.setFontSize(ptSize)

    def insertLayer(self, index, name=None, data=None):
        '''
        insert a new image as layer
        ...add new / override existing layer
        ...show dialog when data.shape != self.image.shape
        '''
        if data is not None:
            try:
                self.image = np.insert(self.image, index, data, axis=0)

            except IndexError:
                index = -1
                self.image = np.insert(self.image, index, data, axis=0)

            except (ValueError, MemoryError):
                if index == 0 and len(self.image) == 1:
                    #replace, if only has one layer
                    self.image = np.expand_dims(data, axis=0)
                else:
                    if type(data) == list:
                        data = data[0]

                    s1 = self.image[0].shape
                    s2 = data.shape
                    #LAYER COLOR IS DIFFERENT:
                    c1 = isColor(self.image[0])
                    c2 = isColor(data)
                    if c1 and not c2:
                        data = toColor(data)
                        s2 = data.shape
                    elif not c1 and c2:
                        self.image = toColor(self.image)
                        s1 = self.image[0].shape
                    if s1 != s2:
                        #NEW LAYER SHAPE DOESNT FIT EXISTING:
                        ###show DIALOG#####
                        d = DifferentShapeDialog(name, s1, s2)
                        d.exec_()

                        r = d.opt
                        if r == d.optNewDisplay:
                            self.moveLayerToNewImage = index
                            return
                        elif r == d.optCut:
                            data = data[0:s1[0], 0:s1[1]]
                            if data.shape != s1:
                                d = np.zeros(s1)
                                d[0:s2[0], 0:s2[1]] = data
                                data = d
                        elif r == d.optResize:
                            data = cv2.resize(data, (s1[1], s1[0]))

                        elif r == d.optWarp:
                            data = PerspectiveTransformation(
                                self.image[-1]).fitImg(data)

                    self.image = np.insert(self.image, index, data, axis=0)

            self.currentIndex = index
            self.setImage(self.image)
            return self.image[index]

    def insertMovedLayer(self, index):
        self.insertLayer(index, data=self._moved_layer)

    def addLayer(self, name=None, data=None, index=None):
        '''
        add a new image as layer the the and of the image stack
        '''
        if self.image is not None:
            if index is None:
                index = len(self.image)
            self.insertLayer(index, data=data)
        else:
            self.update(data)
        self.updateView()
        if self.image is not None:
            self.setCurrentIndex(len(self.image))

    def removeLayer(self, index, toMove=False):
        if self.moveLayerToNewImage is None or self.moveLayerToNewImage != index:
            if toMove:
                if self.image is not None:
                    self._moved_layer = self.image[index]
                else:
                    self._moved_layer = None
            self.image = np.delete(self.image, index, axis=0)
            s = self.image.shape[0]
            if s == 0:
                self.setImage(np.zeros((1, 3, 3)))
                self.image = None
            else:
                #TODO: has last index, if addWidget was called before
                #therefore index cannot be preserved when layers are limited
                i = self.currentIndex
                if index != 0 and i == index:
                    i -= 1
                self.setImage(self.image)
                self.setCurrentIndex(i)
        #reset:
        self.moveLayerToNewImage = None

    def clear(self):
        self.setImage(np.zeros((1, 3, 3)))
        self.image = None
        for name in self.cItems:
            self.removeColorLayer(name)

    def getData(self, index=None):
        '''
        return all image layers or one specified by index
        '''
        if self.image is None:
            return None
        if index is not None:
            return self.image[index]
        return self.image

    def update(self, data=None, index=None, label=None, **kwargs):
        '''
        update either the full image or an image layer
        '''
        if data is not None:
            data = np.asarray(data)
            if index is not None and self.image is not None:
                try:
                    self.image[index] = data
                except (ValueError, IndexError):
                    self.insertLayer(index, name=label, data=data)
            else:
                #set all layers
                if (data.ndim == 2  #single grayscale
                        or data.ndim == 3
                        and data.shape[2] in (3, 4)):  #single color
                    data = np.expand_dims(data, axis=0)
                self.image = data
                self._image_redefined = True
        self._set_kwargs = kwargs
        self._set_index = index
        self._changed = True

    def updateView(self, force=False):
        '''
        update the visual representation
        '''
        if self.image is not None and (force or self._changed):

            if self._image_redefined or self._set_kwargs or self._firstTime:
                self.setImage(self.image, **self._set_kwargs)
                self._firstTime = False
                self._image_redefined = False

            elif force or self._set_index == None or self._set_index == self.currentIndex:
                self.imageDisp = None  # needed by ImageView to set histogram levels
                self.updateImage(**self._set_kwargs)
                if self.opts['autoLevels']:
                    self.autoLevels()
            self._changed = False

    def updateImage(self, autoHistogramRange=None):
        '''
        overwrite original method to hide timeline when 
        3d image has only one layer
        '''
        ## Redraw image on screen
        if self.image is None:
            return

        if autoHistogramRange == None:
            autoHistogramRange = self.opts['autoHistogramRange']

        image = self.getProcessedImage()
        if autoHistogramRange:
            self.ui.histogram.setHistogramRange(self.levelMin, self.levelMax)
        if self.axes['t'] is not None:
            #show/hide timeline:
            self.ui.roiPlot.setVisible(self.image.shape[0] > 1
                                       and self._timeline_visible)
            image = image[self.currentIndex]

        # ensure initial right scaling (not done when image is [0...1]
        # TODO: fix the origin bug
        if image.dtype == bool:
            return self.imageItem.updateImage(image, levels=(0., 1.))
        else:
            self.imageItem.updateImage(image)
コード例 #6
0
ファイル: countLines.py プロジェクト: radjkarl/dataArtist
# coding=utf-8
'''
Count coded lines of all projects
'''
from fancytools.utils.countLines import countLines
from fancytools.os.PathStr import PathStr

d = PathStr.getcwd().dirname()

countLines([
    d.join('dataArtist'),
    d.join('fancyTools'),
    d.join('fancyWidgets'),
    d.join('appBase'),
    d.join('imgprocessor'),
    # d.join('pvimgprocessor'),
    d.join('interactiveTutorial'),
    d.join('headerSetter')
], exclude_folders_containing=("DUMP", 'dist', 'dev', 'build', 'fancytools3'),
    exclude_blank_lines=True,
    exclude_commented_lines=True,
    count_only_py_files=True)