예제 #1
0
    def drawCell(self, p, x0, x1, y0, y1, subx, suby):
        w, h = x1 - x0, y1 - y0
        rect = QtCore.QRectF(x0, y0, w, h)
        # rect:
        pp1 = QtGui.QPainterPath()
        pp1.addRect(rect)
        # busbars:
        # TODO: make width variable ... currently fixed to 1e-3
        ps = QtGui.QPainterPath()
        for yi in subx:
            yi = y0 + yi * (y1 - y0)
            ps.addRect(QtCore.QRectF(x0, yi, w, 1e-3))

        for xi in suby:
            xi = x0 + xi * (x1 - x0)
            ps.addRect(QtCore.QRectF(xi, y0, 1e-3, h))

        if not self.circleOffs.isNull():
            # intersect rect with ellipse to create pseudo rect shape:
            # scale rect:
            c = rect.center()
            esize = rect.size() * 2**0.5 - self.circleOffs
            esize.setWidth(max(rect.width(), esize.width()))
            esize.setHeight(max(rect.height(), esize.height()))

            rect.setSize(esize)
            rect.moveCenter(c)

            pp2 = QtGui.QPainterPath()
            pp2.addEllipse(rect)
            pp1 = pp2.intersected(pp1)
            ps = pp2.intersected(ps)
        p.addPath(ps)
        p.addPath(pp1)
예제 #2
0
    def __init__(self,
                 nCells=(3, 4),
                 nSublines=(0, 0),
                 pos=(0, 0),
                 size=(1, 1),
                 width=(0, 0),
                 **kwargs):
        QuadROI.__init__(self, pos=pos, size=size, removable=True, **kwargs)
        self.nCells = list(nCells)
        self.nSublines = list(nSublines)

        self._shape = None
        self._size = size
        self.width = width
        self.circleOffs = QtCore.QSizeF(0, 0)

        self.homography()

        self._hCellSize = HH(self.setWidth2,
                             self.handleSize,
                             typ='s',
                             pen={
                                 'color': 'b',
                                 'width': 3
                             },
                             parent=self)
        self._hCellShape = HH(self.setCircle,
                              self.handleSize,
                              typ='s',
                              pos=(0.5, 1),
                              pen={
                                  'color': 'c',
                                  'width': 3
                              },
                              parent=self)
예제 #3
0
    def __init__(self, display):
        Tool.__init__(self, display)

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self._grabImage)
        self.firstTime = True

        pa = self.setParameterMenu()

        self.pGrayscale = pa.addChild({
            'name': 'Grayscale',
            'type': 'bool',
            'value': True}) 

        self.pFloat = pa.addChild({
            'name': 'To float',
            'type': 'bool',
            'value': True}) 
        
        pFrequency = pa.addChild({
            'name': 'Read frequency [Hz]',
            'type': 'float',
            'value': 20.0,
            'limits':[0,1000]}) 
        pFrequency.sigValueChanged.connect(self._setInterval)
        
        self._setInterval(pFrequency, pFrequency.value())

        self.pBuffer = pa.addChild({
            'name': 'Buffer last n images',
            'type': 'int',
            'value': 0}) 
예제 #4
0
 def painterPath(self):
     p = QPainterPath()
     roundness = int(99 * float(self._alen) / 16 / 90)
     r = QtCore.QRectF(self._rect)
     r.moveTo(self.state['pos'])
     p.addRoundRect(r, roundness)
     return p
예제 #5
0
 def showDisplay(self, arg):
     '''
     show display as frame-less window 
     '[displaynumber], [area]' = (x,y,width,height)
     '''
     displaynumber, pos = eval(arg)
     if not pos:
         return self.hideDisplay(displaynumber)
     else:
         (x, y, width, height) = pos
     d = self.framelessDisplays.get(displaynumber, None)
     if not d:
         try:
             d = self.currentWorkspace().displaydict()[displaynumber]
             d.release()
             d.hideTitleBar()
             d.setWindowFlags(QtCore.Qt.FramelessWindowHint
                              | QtCore.Qt.WindowStaysOnTopHint)
             self.framelessDisplays[displaynumber] = d
         except KeyError:
             print('displaynumber [%s] not known' % displaynumber)
             return
     d.move(QtCore.QPoint(x, y))
     d.resize(width, height)
     d.show()
예제 #6
0
    def __init__(self, display):
        QtCore.QThread.__init__(self)

        self.display = display
        self.progressBar = display.workspace.gui.progressBar
        self._status_timer = QtCore.QTimer()
        self._curFile_n = 0
        self._firstTime = True
예제 #7
0
 def start(self):
     '''
     configure the server and check the 
     message-inbox every self.opts['refeshrate']
     '''
     self.configure()
     self.timer = QtCore.QTimer()
     self.timer.timeout.connect(self.checkInbox)
     self.timer.start(self.opts['refreshrate'])
예제 #8
0
    def getFileInfo(self, filename):
        '''
        return general information of the given [filename], like it's size
        '''
        f = QtCore.QFileInfo(filename)
        size = f.size()
        size_type = ['Byte', 'kB', 'MB', 'GB', 'TB', 'PB']
        size_index = 0
        while size > 1024:
            size /= 1024.0
            size_index += 1

        size = "%.3g %s" % (round(size, 3), size_type[size_index])
        n = f.fileName()
        return '''File name:\t%s
Folder:\t%s
File type:\t%s
File size:\t%s
Last changed:\t%s''' % (n, f.filePath()[:-len(n)], f.suffix(), size,
                        f.lastModified().toString())

    #TODO: not used at the moment
    #but useful


#     def getMetaData(self, filename):
#         '''
#         Find and format the meta data of [filename]
#         '''
#         text = ""
#         if  filename.filetype().lower() not in ('tif', 'tiff'):
#             #for all files except TIF
#             filename, realname = unicodeFilename(filename), filename
#             parser = createParser(filename, realname)
#             if not parser:
#                 print  "Unable to parse file"
#             try:
#                 metadata = extractMetadata(parser)
#             except HachoirError, err:
#                 #AttributeError because hachoir uses
#                 print "Metadata extraction error: %s" % unicode(err)
#                 metadata = None
#             if not metadata:
#                 print "Unable to extract metadata"
#             else:
#                 text = "\n".join(metadata.exportPlaintext())
#         else:
#             #for TIF images
#             import exifread
#             # Open image file for reading (binary mode)
#             f = open(filename, 'rb')
#             # Return Exif tags
#             tag_dict = exifread.process_file(f)
#             for key, value in tag_dict.iteritems():
#                 text += "%s: %s\n" %(key, value)
#         return text
예제 #9
0
class _Timer(QtCore.QTimer):
    '''
    A QTimer with 2 new signals. emitted, when the timer...
    * started, and
    * stopped
    '''
    sigStarted = QtCore.pyqtSignal(object)  #self
    sigStopped = QtCore.pyqtSignal(object)  #self

    def start(self, msec=None):
        self.sigStarted.emit(self)
        if msec:
            QtCore.QTimer.start(self, msec)
        else:
            QtCore.QTimer.start(self)

    def stop(self):
        QtCore.QTimer.stop(self)
        self.sigStopped.emit(self)
예제 #10
0
 def start(self):
     '''
     configure the server and check the 
     message-inbox every self.opts['refeshrate']
     '''
     self._files = PathStr(self.opts['folder']).listdir()
     
     self.timer = QtCore.QTimer()
     self.timer.timeout.connect(self.checkFolder)
     self.timer.start(self.opts['refreshrate'])
예제 #11
0
    def _edgePos(self, w=None):
        # returns handle position
        t = self.roi._homography
        n = self.roi.nCells

        if w is None:
            w = self.roi.width
        p = self.pos
        return t.map(
            QtCore.QPointF(((p[0] - w[1]) / n[1]), (p[1] - w[0]) / n[0]))
예제 #12
0
 def _prepare(self):
     r = self.boundingRect()
     r = QtCore.QRectF(r.x() / r.width(), r.y() / r.height(), 1, 1)
     #get draw params:
     self._edges, self._angles, self._alen = self._intersectionPointsAndAngles(
         r, self._ratioEllispeRectangle)
     #scale rect:
     bl = r.bottomLeft()
     tr = r.topRight()
     size = tr - bl
     newSize = size * self._ratioEllispeRectangle
     ds = 0.5 * (newSize - size)
     r.setBottomLeft(bl - ds)
     r.setTopRight(tr + ds)
     self._rect = r
예제 #13
0
파일: Tool.py 프로젝트: VaporC/dataArtist
class _ProcessThread(QtCore.QThread):
    '''
    Thread to be used in tool.activate in order not to block 
    the gui 
    '''
    sigDone = QtCore.pyqtSignal(object)

    def __init__(self, tool, runfn, donefn=None):
        QtCore.QThread.__init__(self)
        self.tool = tool
        self.progressBar = tool.display.workspace.gui.progressBar
        self.runfn = runfn
        
        self.sigDone.connect(self.done)
        if not donefn is None:
            self.sigDone.connect(donefn)


    def kill(self):
        self.progressBar.hide()
        self.progressBar.cancel.clicked.disconnect(self.kill)
        self.tool.setChecked(False)
        self.terminate()


    def start(self):
        self.progressBar.show()
        self.progressBar.cancel.clicked.connect(self.kill)
        self.progressBar.bar.setValue(50)
        self.progressBar.label.setText("Processing %s" %self.tool.__class__.__name__)
        QtCore.QThread.start(self)


    def done(self):
        self.progressBar.hide()
        self.progressBar.cancel.clicked.disconnect(self.kill)
        

    def run(self):
        try:
            out = self.runfn()
        except Exception:
            print 'tool activation aborted: %s' %traceback.format_exc()
            return self.progressBar.cancel.click()
        self.sigDone.emit(out)
예제 #14
0
    def __init__(self, scriptTab, automation, refreshrate):
        QtCore.QThread.__init__(self)

        self.scriptTab = scriptTab
        self.automation = automation
        #CREATE AND EXTEND THE GLOBALS USED FOR EXECUTING THE SCRIPT:
        self._globals = _ExecGlobalsDict(automation.display)
        self._globals.update({  #'wait':self.wait,
            'timed': self._getAndRegisterTimer,
            'new': self._addActiveWidget
        })
        k = self._globals.keys()
        for b in BUILTINS_DICT.keys():
            k.remove(b)

        self._widgetUpdateTimer = QtCore.QTimer()
        self._widgetUpdateTimer.timeout.connect(self.automation._updateWidget)
        self.setRefreshrate(refreshrate)
예제 #15
0
    def __init__(self, display):
        Tool.__init__(self, display)

        self.paths = []
        #min time difference to add a line to qpainterpath
        #when drawing in [ms]:
        self.MIN_DT = 25
        self._timer = QtCore.QTime()

        self.pa = self.setParameterMenu()
        self.pa.sigChildRemoved.connect(self._removePath)

        self.pType = self.pa.addChild({
            'name':
            'Type',
            'type':
            'list',
            'value':
            'Freehand',
            'limits': ['Freehand', 'Rectangle', 'Grid', 'Isolines', 'Ellipse']
        })

        self.pNew = self.pa.addChild({
            'name': 'New',
            'type': 'action',
            'value': True
        })
        self.pNew.sigActivated.connect(self._new)
        self.pNew.sigActivated.connect(self._menu.resizeToContent)

        pMask = self.pa.addChild({'name': 'Create Mask', 'type': 'action'})
        pMask.sigActivated.connect(self._createMaskFromSelection)

        pArea = self.pa.addChild({'name': 'Measure areas', 'type': 'action'})
        pArea.sigActivated.connect(self._measurePath)

        self.pMask = pArea.addChild({
            'name': 'Relative to selection',
            'type': 'list',
            'value': '-',
            'limits': ['-']
        })
        self.pMask.items.keys()[0].widget.showPopup = self._updatePMask
예제 #16
0
    def __init__(self, display):
        Tool.__init__(self, display)

        self.paths = []
        #min time difference to add a line to qpainterpath
        #when drawing in [ms]:
        self.MIN_DT = 25
        self._timer = QtCore.QTime()

        self.pa = self.setParameterMenu()
        self.pa.sigChildRemoved.connect(self._removePath)

        pNew = self.pa.addChild({
            'name': 'New',
            'type': 'action',
            'value': True
        })
        pNew.sigActivated.connect(self._newCurve)
        pNew.sigActivated.connect(self._menu.hide)
예제 #17
0
    def __init__(self, name, widget, pkg, toolClasses):
        QtGui.QToolBar.__init__(self, name)

        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._openContextMenu)
        #make ToolBar smaller:
        self.setIconSize(QtCore.QSize(16, 16))
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.setAllowedAreas(QtCore.Qt.TopToolBarArea)

        #measure toolbar width in order to find best place when added
        self.width = 9  #9=handle width

        # whether position of toolbar should be
        #found depending on available space:
        #         self.needPositioning = False

        name[0].islower()
        f = name[0]
        if f.islower():
            name = f.upper() + name[1:]
        self.name = name

        self.widget = widget
        self.toolClasses = toolClasses
        self._toolsCreated = False

        # there is a central setup for the visibility of all
        # toolbars that have the same display widget:
        show = getattr(pkg, 'show', True)
        if isinstance(show, dict):
            #whether to show/hide a toolbar depends on the chosen profile:
            session = QtGui.QApplication.instance().session
            profile = session.app_opts.get('profile', None)
            show = show.get(profile, False)
        if self.widget.__class__.selectedToolbars.get(name, None) is None:
            self.widget.__class__.selectedToolbars[name] = [
                show,
                #                             QtCore.Qt.TopToolBarArea,
                #                             TO_QT_POSITION[getattr(pkg, 'position','top')],
                False
            ]  #->hasBreak

            #         #add logo to toolbar:
            #         icon  = getattr(pkg, 'icon', None)
            #         if icon:
            #             #icon can ge given as direct path
            #             if not os.path.exists(icon):
            #                 #otherwise it is assumed that
            #                 #the icon is to be found in the icon directory:
            #                 icon = ICONFOLDER.join(icon)
            #             s = ToolBarIcon(self, icon)

            tip = getattr(pkg, '__doc__', None)
            ttname = name
            if tip:
                ttname += '\n\t%s' % tip
            self.setToolTip(ttname)

        #BACKGROUND COLOR:
        c = getattr(pkg, 'color', None)
        if not c is None:
            #create a semi-transparent colour from
            #normal background color (grey)
            #and given color:
            a = 0.9
            b = 1 - a
            p = self.palette()
            bg = p.color(self.backgroundRole())
            c = QtGui.QColor(c)
            bg.setRed(a * bg.red() + b * c.red())
            bg.setGreen(a * bg.green() + b * c.green())
            bg.setBlue(a * bg.blue() + b * c.blue())
            self.setBackgroundRole(QtGui.QPalette.Window)
            p.setColor(self.backgroundRole(), bg)
            self.setPalette(p)
            self.setAutoFillBackground(True)

        self.actionSelect = a = QtGui.QAction(name, self)
        s = 'contains...'
        for cls in self.toolClasses:
            s += '\n     %s' % cls.__name__
        a.setToolTip(s)
        a.setCheckable(True)
        a.setChecked(show)
        a.triggered.connect(self.setSelected)
예제 #18
0
class ReaderBase(QtCore.QThread):
    '''
    Base class for file reader
    reading input files within a QThread in order not to block the screen
    Show progress in progress bar
    '''                      #array, filenames, labels
    done = QtCore.pyqtSignal(object, object, object)
    preferences = None
    forceSetup = False  #whether to show import preferences on the first time

    def __init__(self, display):
        QtCore.QThread.__init__(self)

        self.display = display
        self.progressBar = display.workspace.gui.progressBar
        self._status_timer = QtCore.QTimer()
        self._curFile_n = 0
        self._firstTime = True

    @classmethod
    def check(cls, ftype, fname):
        return ftype in cls.ftypes

    def _cancel(self):
        self.canceled = True

    def toFloat(self, arr, toFloat=True, forceFloat64=False):
        if hasattr(self, 'preferences'):
            p = self.preferences
            toFloat = p.pToFloat.value()
            forceFloat64 = p.pForceFloat64.value()

        if not toFloat:
            return arr
        arr = np.asanyarray(arr)
        try:
            if forceFloat64:
                dtype = np.float64
            else:
                dtype = {
                    np.dtype('uint8'): np.
                    float32,  #float16 is just to coarse and cause nans and infs
                    np.dtype('uint16'): np.float32,
                    np.dtype('uint32'): np.float64,
                    np.dtype('uint64'): np.float64
                }[arr.dtype]
            return arr.astype(dtype, copy=False)
        except KeyError:
            return arr

    def status(self):
        '''
        returns the ratio of progress 
        (should be overridden in child class)
        '''
        return 1

    def overallStatus(self):
        '''
        return the overall readout status in percent
        '''
        return 100 * self.status() * float(self._curFile_n + 1) / len(
            self.filenames)

    def start(self, filenames):
        self.filenames = filenames

        if self.preferences and self.forceSetup and self._firstTime:
            d = QtGui.QDialog()
            d.setWindowTitle('Import preferences')

            l = QtGui.QVBoxLayout()
            t = ParameterTree(self.preferences)
            b = QtGui.QPushButton('OK')
            b.clicked.connect(d.accept)

            l.addWidget(t)
            l.addWidget(b)

            d.setLayout(l)

            d.accepted.connect(self._start)
            d.exec_()
        else:
            self._start()

    def _start(self):
        self.canceled = False
        self._firstTime = False

        #PROGRESS BAR:
        self.progressBar.show()
        self.progressBar.cancel.clicked.connect(self._cancel)
        self.progressBar.bar.setValue(0)
        self._status_timer.timeout.connect(
            lambda: self.progressBar.bar.setValue(self.overallStatus()))
        self._status_timer.start(1000)  #[ms] -> every second

        self.finished.connect(self.cleanUp)

        QtCore.QThread.start(self)

    def run(self):
        '''
        read data from given self.filenames
        
        returns datalayers, filenames, layernames
        '''
        data_list = []
        label_list = []
        fname_list = []
        for self._curFile_n, f in enumerate(self.filenames):
            if f:
                self.progressBar.label.setText("open file '%s'" % f)
                #GET DATA:
                try:
                    data, labels = self.open(f)
                    if data is None:
                        raise IOError('data empty')
                    if labels is not None:
                        # multiple plots/images/etc in one file:
                        data_list.extend([d for d in data])
                        label_list.extend(labels)
                        fname_list.extend([f] * len(labels))
                    else:
                        data_list.append(data)
                        label_list.append(labels)
                        fname_list.append(f)

                except (IOError, ValueError), errmsg:
                    print 'Error while opening %s: %s' % (f, errmsg)
                    label_list.append(None)
                    data_list.append(None)
                    fname_list.append(f)

                if self.canceled:
                    break
        self.done.emit(data_list, fname_list, label_list)
예제 #19
0
파일: Fit.py 프로젝트: VaporC/dataArtist
class _ControlWidget(QtGui.QWidget):
    '''
    A draggable control window with:
    * Button 'Previous'
    * Button 'Next'
    to be connected with the given functions
    '''
    sigDone = QtCore.Signal(tuple)  #parameter values

    def __init__(self, parameters, function, xVals, plotItem):
        QtGui.QWidget.__init__(self)

        #make frame-less:
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint
                            | QtCore.Qt.WindowStaysOnTopHint)
        #TODO:
        #         #go to current screen:
        #         d = QtGui.QApplication.desktop()
        #         n = d.screenNumber(self)
        #         self.setGeometry(d.screenGeometry(n))

        self.xVals = xVals
        self.plotItem = plotItem
        self.function = function

        layout = QtGui.QGridLayout()
        self.setLayout(layout)

        self.s = []  #all spinboxes

        for n, (name, value) in enumerate(parameters.items()):
            layout.addWidget(QtGui.QLabel(name), n, 0)
            s = QtGui.QDoubleSpinBox()
            s.setValue(value)
            s.setMaximum(1e6)
            s.setMinimum(-1e6)

            s.valueChanged.connect(self._valueChanged)
            layout.addWidget(s, n, 1)
            self.s.append(s)

        btn_done = QtGui.QPushButton('Done')
        btn_done.clicked.connect(self.done)
        layout.addWidget(btn_done, n + 1, 0, 1, 2)

        self._valueChanged()

    def _getVals(self):
        vals = []
        for s in self.s:
            vals.append(s.value())
        return vals

    def _valueChanged(self):
        yVals = [self.function(x, *tuple(self._getVals())) for x in self.xVals]

        self.plotItem.setData(self.xVals, yVals)

    def done(self):
        self.close()
        self.sigDone.emit(tuple(self._getVals()))

    #make draggable:
    def mousePressEvent(self, event):
        self.offset = event.pos()

    def mouseMoveEvent(self, event):
        x = event.globalX()
        y = event.globalY()
        x_w = self.offset.x()
        y_w = self.offset.y()
        self.move(x - x_w, y - y_w)
예제 #20
0
class _StackParameter(GroupParameter):
    '''
    Parameter containing information about all input layers and 
    allowing to change their position within the stack
    '''
    sigValuesChanged = QtCore.pyqtSignal(object)  #values
    sigLayerNameChanged = QtCore.pyqtSignal(int, object)  #index, name

    def __init__(self, display):
        self.display = display

        mAll = QtGui.QMenu('All layers')
        mAll.addAction('Change').triggered.connect(
            self.display.changeLayerFiles)
        mAll.addAction('Remove').triggered.connect(self.display.removeLayers)

        GroupParameter.__init__(
            self, **{
                'name': '   Layers',
                'sliding': True,
                'addToContextMenu': [mAll]
            })
        #IF A LAYER IS MOVED:
        self.sigChildRemoved.connect(
            lambda parent, child, index, self=self: self.display.removeLayer(
                index, self.opts.get('aboutToMove', False)))
        self._fnInsertRemovedLayer = lambda parent, child, index, self=self: \
                                        self.display.insertRemovedLayer(index)
        self.sigChildAdded.connect(self._fnInsertRemovedLayer)
        self.sigChildAdded.connect(self._valuesChanged)
        self.sigChildRemoved.connect(self._valuesChanged)

    def _extractFromOrigin(self, origin, index, info, changes):
        '''
        get 'Info' and 'Changes' from origin StackParameter
        append origin-changes with new changes
        '''
        if origin:
            ch = origin.children()
            if not info:
                info = [c.param('Info').value() for c in ch]
                if index is not None:
                    info = info[index]
                else:
                    info = '\n---\n'.join(info)
            origin_changes = ''
            for c in ch:
                v = c.param('Changes').value()
                if len(v):
                    origin_changes += ';%s ' % v
            if changes:
                if type(changes) in (tuple, list):
                    changes = changes[index]
                changes += '\n%s' % origin_changes
            else:
                changes = origin_changes
        return info, changes

    def _valuesChanged(self):
        '''
        all layers create an additional stack-dimension with it's own values
        e.g. a set of images, where every layer represents an image at another excitation time
           could have stack.values = [1,5,10,15,20] [s] 
           as soon as the position of a layer changed or a layer is removed
           these values (e.g.excitation times) have to updated as well
        '''
        self.values = np.array([ch.value() for ch in self.childs])
        self.sigValuesChanged.emit(self.values)

#
#     def save(self, session, path):
#         '''
#         save parameter values to file 'stack.txt'
#         '''
#         session.addContentToSave(self.saveState(), *path+('stack.txt',))
#

    def restoreState(self, state, **kwargs):
        '''
        set parameter values using file 'stack.txt'
        '''
        #DON'T DO ANYTHING WHILE THE STACK IS UPDATED:
        self.blockSignals(True)
        self.clearChildren()
        self.blockSignals(False)
        self.sigChildAdded.disconnect(self._fnInsertRemovedLayer)
        #REBUILD STACK:
        #         l =  eval(session.getSavedContent(*path +('stack.txt',) )  )
        GroupParameter.restoreState(self, state, **kwargs)
        self.sigChildAdded.connect(self._fnInsertRemovedLayer)

    def buildLayer(self,
                   fname,
                   label,
                   name,
                   data,
                   origin=None,
                   index=None,
                   info=None,
                   changes=None):
        '''
        for every layer of the stack add a parameter containing ...
        * it's stack value
        * an layer info field
        * a layer changed field
        '''
        info, changes = self._extractFromOrigin(origin, index, info, changes)
        try:
            self.sigChildAdded.disconnect(self._fnInsertRemovedLayer)
        except TypeError:
            pass

        #ADD OPTIONS TO THE CONTEXT MENU:
        mCopy = QtGui.QMenu('Copy')
        mMove = QtGui.QMenu('Move')

        if not fname or not PathStr(fname).isfile():
            fname = None

        menu_entries = [mCopy, mMove]
        if self.display.reader is not None:
            aFile = QtGui.QAction('Change File', self)
            aFile.triggered.connect(lambda checked, i=len(self.childs): self.
                                    display.changeLayerFile(i))
            menu_entries.append(aFile)
        #CREATE AND ADD COPY-LAYER-TO OPTION TO PARAMETER:
        pLayer = self.addChild({
            'type':
            'float',
            'highlight':
            True,
            'name':
            name,
            'value':
            self.display.axes.stackAxis.getNextStackValue(
                PathStr(fname).basename()),
            'expanded':
            False,
            'removable':
            True,
            'autoIncrementName':
            True,
            'renamable':
            True,
            'readonly':
            True,
            'addToContextMenu':
            menu_entries,
            'filename':
            fname,
            'layername':
            label,
        })
        mCopy.aboutToShow.connect(
            lambda pLayer=pLayer, mCopy=mCopy, self=self: self.
            buildCopyToDisplayMenu(mCopy, pLayer, 'copy'))
        mMove.aboutToShow.connect(
            lambda pLayer=pLayer, mMove=mMove, self=self: self.
            buildCopyToDisplayMenu(mMove, pLayer, 'move'))

        #UPDATE STACK VALUES:
        pLayer.sigValueChanged.connect(self._valuesChanged)
        #EMIT LAYERNAMESCHANGED:
        pLayer.sigNameChanged.connect(
            lambda param, val, self=self: self.sigLayerNameChanged.emit(
                param.parent().children().index(param), val))
        #CHECK WHETHER INSERTED LAYER COMES FROM A MOVED ONE:
        self.sigChildAdded.connect(self._fnInsertRemovedLayer)
        #ADD LAYER INFO
        if info is None:
            finfo = ''
            if fname is not None:
                try:
                    #read info from file:
                    finfo += self.getFileInfo(
                        fname) + '\n'  # + self.getMetaData(name)
                except AttributeError:
                    pass
                #    finfo = '' #not possible to read from file because maybe not a filename
            dinfo = ''
            if data is not None:
                try:
                    dinfo = 'shape:\t%s\ndtype:\t%s' % (data.shape, data.dtype)
                except AttributeError:
                    #data in not array
                    dinfo = 'length: %s' % len(data)
            info = '%s---\n%s' % (finfo, dinfo)

        if isinstance(info, Parameter):
            #CASE: layer was duplicated and [info] is a parameter
            for ch in info.children():
                pLayer.addChild(ch.duplicate())
        else:
            #info is given as text
            #LAYER INFO
            pLayer.addChild({
                'type': 'text',
                'name': 'Info',
                'value': info if info != None else '',
                'readonly': True
            })
        #LAYER CHANGES
        pLayer.addChild({
            'type': 'text',
            'name': 'Changes',
            #'TODO: every change through a tool/scripts operation to be added here',
            'value': changes if changes else '',
            #'readonly':True
            'expanded': bool(changes)
        })

    def addChange(self, change, index=None):
        if change is not None:
            ch = self.children()
            if index is not None:
                ch = [ch[index]]

            if type(change) not in (tuple, list):
                change = [change] * len(ch)

            for n, c in enumerate(ch):
                p = c.param('Changes')
                v = p.value()
                if not v:
                    p.setValue(change[n])
                    p.setOpts(expanded=True)
                else:
                    p.setValue('%s\n%s' % (p.value(), change[n]))

    def buildCopyToDisplayMenu(self, menuCopy, paramFile, method):
        '''
        clear the context menu 'copy'
        add 'NEW' to copy a layer to a new display
        add names of all other displays
        connect all actions to respective display methods
        '''
        menuCopy.clear()

        #NEW:
        if method == 'copy':
            m = self.display.copyLayerToNewDisplay
        else:
            m = self.display.moveLayerToNewDisplay

        menuCopy.addAction('NEW').triggered.connect(
            lambda checked, paramFile=paramFile, m=m: m(paramFile.parent(
            ).children().index(paramFile)))

        #OTHER DISPLAYS:
        if method == 'copy':
            m = self.display.copyLayerToOtherDisplay
        else:
            m = self.display.moveLayerToOtherDisplay

        for d in self.display.workspace.displays():
            if d != self.display and d.widget.__class__ == self.display.widget.__class__:
                menuCopy.addAction(d.name()).triggered.connect(
                    lambda checked, paramFile=paramFile, d=d, m=m: m(
                        paramFile.parent().children().index(paramFile), d))

    def getFileInfo(self, filename):
        '''
        return general information of the given [filename], like it's size
        '''
        f = QtCore.QFileInfo(filename)
        size = f.size()
        size_type = ['Byte', 'kB', 'MB', 'GB', 'TB', 'PB']
        size_index = 0
        while size > 1024:
            size /= 1024.0
            size_index += 1

        size = "%.3g %s" % (round(size, 3), size_type[size_index])
        n = f.fileName()
        return '''File name:\t%s
Folder:\t%s
File type:\t%s
File size:\t%s
Last changed:\t%s''' % (n, f.filePath()[:-len(n)], f.suffix(), size,
                        f.lastModified().toString())

    #TODO: not used at the moment
    #but useful


#     def getMetaData(self, filename):
#         '''
#         Find and format the meta data of [filename]
#         '''
#         text = ""
#         if  filename.filetype().lower() not in ('tif', 'tiff'):
#             #for all files except TIF
#             filename, realname = unicodeFilename(filename), filename
#             parser = createParser(filename, realname)
#             if not parser:
#                 print  "Unable to parse file"
#             try:
#                 metadata = extractMetadata(parser)
#             except HachoirError, err:
#                 #AttributeError because hachoir uses
#                 print "Metadata extraction error: %s" % unicode(err)
#                 metadata = None
#             if not metadata:
#                 print "Unable to extract metadata"
#             else:
#                 text = "\n".join(metadata.exportPlaintext())
#         else:
#             #for TIF images
#             import exifread
#             # Open image file for reading (binary mode)
#             f = open(filename, 'rb')
#             # Return Exif tags
#             tag_dict = exifread.process_file(f)
#             for key, value in tag_dict.iteritems():
#                 text += "%s: %s\n" %(key, value)
#         return text
예제 #21
0
class DisplayDock(Dock):
    '''
    A Dock container to...
    
    * OPEN and DISPLAY given input within a fitting display widget 
         (e.g. display.Image for images)
    * adding, (re)moving, copying input LAYERS (e.g. multiple plots 
         or images of the same size)
    * choosing the right TOOLS for the corresponding display widget
    * creating PREFERENCES in INFORMATION about the input 
    '''
    clicked = QtCore.pyqtSignal(object)  #self
    closed = QtCore.pyqtSignal(object)  #self
    sigLayerChanged = QtCore.pyqtSignal(object)  #self
    sigNewLayer = QtCore.pyqtSignal(object)  #self

    def __init__(self,
                 number,
                 workspace,
                 origin=None,
                 index=None,
                 names=None,
                 title='',
                 data=None,
                 axes=None,
                 info=None,
                 changes=None,
                 openfiles=True):
        '''
        ============   ===============================================
        Arguments      Description
        ============   ===============================================        
        number         The display number, like 1,2...
        workspace      The workspace within the display is
        names          Path(s) of input files to open
        title          ... of the DisplayDock
        data           ... to display within the corresponding widget
        axes           Instance of AxesContainer with names and scales
                       for the axes scaling the data
        origin         The origin display
        index          The index of the origin layer
        info           informational text about the input
        changes        Additional changes done to the data
        openfiles      [True/False] whether to open the files
                       given in [filenames]
        ============   ===============================================
        '''
        self.workspace = workspace
        self.number = number

        self.widget = None

        self._isclosed = False

        #GET VALUES FROM ORIGIN DISPLAY
        data, names, axes, title = self._extractInfoFromOrigin(
            origin, index, data, names, axes, title)
        if data is None and names is None and axes is None:
            raise Exception('either filenames, data or axes must be given')
        one_layer = False

        #FORMAT FILENAMES TO A LIST OF FILENAMES:
        if names is None:
            if data is not None:
                names = [None] * len(data)
            else:
                names = []
        elif isinstance(names, basestring):
            names = [names]
            one_layer = True

        docktitle = self._getDockTitle(title, number, names)

        #INIT SUPER CLASS
        Dock.__init__(self, docktitle)

        #SETUP FILE READER:
        self.reader = None
        if names and data is None:  #-->load input from file
            self.reader = getFileReader(names)
            self.reader = self.reader(weakref.proxy(self))
            #GET AXES FROM INPUT READER IF NOT DEFINED YET:
            if axes is None:
                axes = self.reader.axes
        #CREATE/FORMAT AXES IF INPUT GIVES AS DATA:
        if axes is None:
            axes = ['x', 'y', '', 'i', 'j'][:data[0].ndim + 1]
        elif type(axes) == int:
            axes = ['x', 'y', '', 'i', 'j'][:axes]

        self.stack = _StackParameter(self)

        #PARAMETERS:
        self.p = Parameter.create(name='', type='empty')

        #TAB DISPLAYING PREFERENCES AND INPUT INFORMATION:
        self.tab = _DisplayTab(self)
        #FILL PARAMETERS:
        self.pTitle = self.p.addChild({
            'name': 'Title',
            'type': 'str',
            'value': ''
        })
        self.pTitle.sigValueChanged.connect(self._setWidgetTitle)
        pSize = self.pTitle.addChild({
            'name': 'Size',
            'type': 'int',
            'value': 11
        })
        pSize.sigValueChanged.connect(
            lambda param, size: self.widget.setTitleSize(size))

        self.pTitleFromLayer = self.pTitle.addChild({
            'name': 'From layer',
            'type': 'bool',
            'value': False
        })
        self.pTitleFromLayer.sigValueChanged.connect(
            self._pTitleFromLayerChanged)

        self.pLimitLayers = self.p.addChild({
            'name': 'Limit Layers',
            'type': 'bool',
            'value': False
        })
        self.pLimitLayers.sigValueChanged.connect(self._pLimitLayersChanged)

        self.pMaxLayers = self.pLimitLayers.addChild({
            'name': 'Max. Layers',
            'type': 'int',
            'value': 10,
            'visible': False,
            'limits': [1, 1e4]
        })

        self.pMaxLayers.sigValueChanged.connect(self._limitLayers)

        #HANDLING THE INPUT LAYERS:
        self.p.addChild(self.stack)
        self.axes = AxesContainer(weakref.proxy(self), axes,
                                  weakref.proxy(self.stack))
        #ADD AXES PARAMETERS:
        self.p.addChild(self.axes.p)
        #LIST OF ALL FITTING DISPLAY FIGURES:
        widgetList = _DisplayFigureList(self)

        #UPDATE DATA FROM FILE USING SPECIFIED PREFERENCES:
        #TODO: 'update' should only update file based data and no processed data
        if self.reader:
            #             pUpdate = Parameter.create(**{
            #                         'type':'action',
            #                         'name':'Update',
            #                         })
            if self.reader.preferences:
                #                 pUpdate.addChild(self.reader.preferences)
                #             pUpdate.sigActivated.connect(self.updateInput)
                self.p.addChild(self.reader.preferences)

        self.p.addChild(widgetList)

        #INIT WIDGET
        self.changeWidget(widgetList.getWidget())  #, data, names)
        #ADD DATA
        if len(names):
            if data is None and PathStr(names[0]).isfile():
                self.addFiles(names, openfiles)
            #TODO: what to do with mixed file/non file input?
            else:
                if one_layer:
                    self.addLayer(data, names[0], origin=origin)
                else:
                    self.addLayers(data, names, origin=origin)

    def otherDisplaysOfSameType(self, includeThisDisplay=False):
        for d in self.workspace.displays():
            if (isinstance(d.widget, self.widget.__class__)
                    and (includeThisDisplay or d.name() != self.name())):
                yield d

    def _limitLayers(self, param, val):
        #remove surplus layers
        for _ in range(len(self.stack.childs) - val):
            self.stack.children()[0].remove()

    def _pLimitLayersChanged(self, p, val):
        p = self.pMaxLayers
        p.show(val)
        if val:
            self._limitLayers(None, p.value())

    def _pTitleFromLayerChanged(self, param, val):
        self.pTitle.setOpts(readonly=val)
        w = self.widget
        if val:
            w.sigTimeChanged.connect(self._setTitleFromCurrentLayer)
            self._setTitleFromCurrentLayer(w.currentIndex)
        else:
            try:
                w.sigTimeChanged.disconnect(self._setTitleFromCurrentLayer)
                self._setWidgetTitle(None, self.pTitle.value())
            except:
                pass

    def _setWidgetTitle(self, param, title):
        if not title:
            title = None
        self.widget.setTitle(title)

    def _setTitleFromCurrentLayer(self, index):
        try:
            self.widget.setTitle(self.stack.childs[index].name())
        except IndexError:
            pass  #there are no layers

    @staticmethod
    def _getDockTitle(title, number, names):
        '''
        create a title for this display dock

        names -> list instances of PathStr
        '''
        docktitle = '[%s] ' % number
        if title:
            docktitle += title
        if len(names) > 1:
            #if multiple files imported:
            #FOLDER IN TITLE
            dirname = PathStr(names[0]).dirname()
            if len(dirname) > 20:
                dirname = '~' + dirname[-20:]
            docktitle += "%s files from %s" % (len(names), dirname)
        elif names and names != [None]:
            #FILENAME IN TITLE
            name = PathStr(names[0]).basename()
            if len(name) > 20:
                name = name[:8] + '(...)' + name[-8:]
            docktitle += name
        return docktitle

    def _extractInfoFromOrigin(self, origin, index, data, names, axes,
                               docktitle):
        '''
        get data, filenames, axes from the origin display
        if there value is None
        '''

        if origin:
            ch = origin.stack.childs
            if index is None:
                if data is None:
                    data = origin.widget.getData()
            else:
                if data is None:
                    data = origin.widget.getData(index)

                ch = [ch[index]]

            if names is None:
                names = [c.name() for c in ch]
                if index is not None:
                    names = names[0]
            if axes is None:
                axes = origin.axes.copy()
            if not docktitle:
                docktitle = 'Child'
            docktitle = '%s of %s' % (docktitle, origin.shortName())
        return data, names, axes, docktitle

    def shortName(self):
        return '[%s]' % self.number


#     def _getNDataLayers(self, axes, data):
#         '''
#         define number of data layers interpreting [data] and it's [axes]
#         '''
#         l = len(axes)
#         #get number of dimensions (nDim) and shape without the need of an ndarray:
#         try:
#             x = data
#             shape = []
#             while True:
#                 shape.append(len(x))
#                 x = x[0]
#         except TypeError:
#             ndim = len(shape)
#         except IndexError:
#             #has no layers jet
#             return 0
#         if l == ndim + 1:
#             #stack with one layer or no stack:
#             nlayers = 1
#         elif l == ndim or l == ndim-1:
#             #multiple layers:
#             nlayers = shape[0]
#         else:
#             raise Exception("number of axes doesn't fit to data shape")
#         return nlayers

    def mousePressEvent(self, event):
        '''
        emits the signal 'clicked' if it is activated
        '''
        self.clicked.emit(weakref.proxy(self))

    def close(self):
        '''
        emits the signal 'closed'
        '''
        Dock.close(self)
        self._isclosed = True
        self.workspace.gui.undoRedo.displayClosed(self)
        self.closed.emit(self)
        self.widget.close()

    def isClosed(self):
        return self._isclosed

    def __getattr__(self, attr):
        '''
        this method is to access display layers easily in the built-in python shell
        
        if attribute cannot be found:
        return data or data-layer if attribute = 'l' or 'l0'...'l[layerNumber]'
        '''
        try:
            Dock.__getattr__(self, attr)
        except AttributeError:
            if attr[0] == 'l':
                a = attr[1:]
                if a != '':
                    if not a.isdigit():
                        raise AttributeError(
                            "display %s doesn't has attribute %s" %
                            (self.name(), attr))
                    a = int(a)
                    return self.widget.getData(a)
                return self.widget.getData()
            else:
                raise AttributeError("display %s doesn't has attribute %s" %
                                     (self.name(), attr))

    def __setattr__(self, attr, value):
        '''
        this method is to access display layers easily in the built-in python shell

        if attribute is 'l' or 'l0'...'l[layerNumber]':
            set all data of a certain data layer to [value]  
        '''
        if attr[0] == 'l':
            a = attr[1:]
            if not a:
                #make sure that this display is updated through automation:
                self.tab.automation.checkWidgetIsActive(self.widget)

                nLayers = len(self.stack.childs)
                # CASE 'l'
                n = self.widget.getNLayers(value)
                #                 n = self._getNDataLayers(self.axes, value)
                #                 print nLayers, n,55555555555
                #                 if not n:
                #                     raise Exception("number of axes doesn't fit to data shape")

                if nLayers == n:
                    #print value
                    return self.widget.update(value)

                if nLayers != 0:
                    #remove old layers:
                    for i in range(nLayers):
                        self.removeLayer(i)
                if n > 1:
                    for layer in value:
                        self.addLayer(data=layer)
                else:
                    return self.addLayer(data=value)
            elif a.isdigit():
                #make sure that this display is updated through automation:
                self.tab.automation.checkWidgetIsActive(self.widget)

                nLayers = len(self.stack.childs)
                # CASE 'l0'...'l[n]'
                a = int(a)
                if a == nLayers:
                    #this index doesn't exist jet - so add a new layer
                    return self.addLayer(data=value)
                return self.widget.update(value, index=a)
        Dock.__setattr__(self, attr, value)

    def duplicate(self):
        '''
        create a new display with the same data and axes
        '''
        d = self.workspace.addDisplay(origin=self, title='Duplicate')
        d.p.restoreState(self.p.saveState())
        d.widget.restoreState(self.widget.saveState())
        return d

    def adaptParamsToWidget(self):
        s = self.widget.shows_one_layer_at_a_time

        self.pTitleFromLayer.show(s)
        if not s:
            #cannot set title from layer if all layers are displayed
            #at the same time
            self._pTitleFromLayerChanged(None, False)

    def changeWidget(self, widgetCls):
        '''
        change the display widget class and setup the toolbar
        '''
        self._reloadWidgetCls(widgetCls)
        #to init the new toolbars:
        self.clicked.emit(self)

        self.adaptParamsToWidget()

    def reloadWidget(self):
        self._reloadWidgetCls(self.widget.__class__)

    def _reloadWidgetCls(self, widgetCls):
        data = None
        state = None
        toolbars = None
        if self.widget:
            data = self.widget.getData()
            state = self.widget.saveState()
            toolbars = self.widget.toolbars

        names = self.layerNames()
        self.widget = widgetCls(weakref.proxy(self),
                                self.axes,
                                data=data,
                                names=names,
                                toolbars=toolbars)
        if state:
            self.widget.restoreState(state)

        Dock.setWidget(self, self.widget)

    def insertRemovedLayer(self, index):
        '''
        Insert a layer moved to [index]
        '''
        self.widget.insertMovedLayer(index)

    def removeLayers(self):
        self.stack.clearChildren()
        self.widget.clear()
        self.filenames[:] = []

    def removeLayer(self, index, toMove=False):
        '''
        remove a data layer
        toMove=True => this layer will be moved within the stack 
        '''
        self.widget.removeLayer(index, toMove)

    def copyLayerToOtherDisplay(self, index, display):
        display.addLayer(origin=self, index=index)

    def moveLayerToOtherDisplay(self, index, display):
        display.addLayer(origin=self, index=index)
        self.stack.childs[index].remove()

    def copyLayerToNewDisplay(self, index):
        self.workspace.addDisplay(origin=self, index=index)

    def moveLayerToNewDisplay(self, index):
        self.copyLayerToNewDisplay(index)
        self.stack.childs[index].remove()

    def layerNames(self):
        '''
        return the names of all data layers
        '''
        return [ch.name() for ch in self.stack.children()]

    @staticmethod
    def _getLayerLabel(fname, label):
        if fname is None:
            if label is None:
                return 'unknown'
            return label
        if PathStr(fname).isfile():
            fname = PathStr(fname).basename()
        if label is not None:
            return '%s - %s' % (label, fname)
        return fname

    def addLayer(self,
                 data=None,
                 filename=None,
                 label=None,
                 origin=None,
                 index=None,
                 info=None,
                 changes=None,
                 **kwargs):
        '''
        Add a new layer to the stack
        '''
        data, filename, _, _ = self._extractInfoFromOrigin(
            origin, index, data, filename, False, False)

        name = self._getLayerLabel(filename, label)
        #ADD TO PARAMETER TREE
        self.stack.buildLayer(filename,
                              label=label,
                              name=name,
                              data=data,
                              origin=origin.stack if origin else None,
                              index=index,
                              info=info,
                              changes=changes)
        #WIDGET
        layer = self.widget.addLayer(name=name, data=data, **kwargs)
        if not self.widget.moveLayerToNewImage is None:
            print 'Move this layer to new display'
            #couldn't add new layer to stack: create a new display to show it
            self.workspace.addDisplay(origin=self,
                                      index=len(self.filenames) - 1,
                                      data=[data])
            self.stack.childs[-1].remove()
        else:
            #LIMIT LAYERS
            if (self.pLimitLayers.value()
                    and len(self.stack.childs) > self.pMaxLayers.value()):
                self.stack.childs[0].remove()
            #AUTOMATION
            self.sigNewLayer.emit(self)
            return layer

    def backupChangedLayer(self,
                           backup=None,
                           changes=None,
                           index=None,
                           **kwargs):
        #UNDO/REDO
        ur = self.workspace.gui.undoRedo
        if ur.isActive():
            #index = kwargs.get('index', None)
            widget = self.widget
            if backup is None:
                data = widget.getData(index)
                if data is None:
                    return
                backup = data.copy()
            name = self.shortName()
            if index is not None:
                name += "-%s" % index
            name += ": %s" % changes

            ur.add(display=self,
                   name=name,
                   undoFn=lambda i=index, d=backup: self.changeLayer(
                       data=d, changes='undo', index=i, backup=False),
                   redoFn=lambda d, i=index: self.changeLayer(
                       data=d, changes='redo', index=i, backup=False),
                   dataFn=lambda i=index, w=widget: w.getData(i).copy())

    def changeAllLayers(self, data=None, changes=None, backup=True, **kwargs):
        if backup:
            self.backupChangedLayer(data, changes, **kwargs)
        self.widget.update(data, **kwargs)
        self.widget.updateView()
        for index in range(len(self.stack.childs)):
            self.stack.addChange(changes, index=index)
        self.sigLayerChanged.emit(self)

    def changeLayer(self,
                    data=None,
                    changes=None,
                    index=None,
                    backup=True,
                    **kwargs):
        if backup:
            self.backupChangedLayer(data, changes, index, **kwargs)
        self.widget.update(data, index=index, **kwargs)
        self.widget.updateView()
        self.stack.addChange(changes, index=index)
        self.sigLayerChanged.emit(self)

    def showToolBar(self, name):
        '''
        show an other toolbar of the same display.widget
        if hidden
        '''
        #make given toolbar tool visible
        found = False
        for t in self.widget.toolbars:
            if t.name.lower() == name.lower():
                t.setSelected(True)
                found = True
                break
        if not found:
            raise Exception('Toolbar [%s] doesnt exist' % name)
        else:
            return t

    def changeLayerFiles(self):
        filt = '*.' + ' *.'.join(self.reader.ftypes)
        fnames = self.workspace.gui.dialogs.getOpenFileNames(filter=filt)
        if fnames:
            self.removeLayers()
            self.addFiles(fnames)

    def changeLayerFile(self, index):
        '''
        change the origin file of layer of [index]
        '''

        filt = '*.' + ' *.'.join(self.reader.ftypes)
        fname = self.workspace.gui.dialogs.getOpenFileName(
            filter=filt, directory=self.filenames[index].dirname())
        if fname is not None:
            self._readFiles([fname], self._updateFiles)

    @property
    def filenames(self):
        return removeDuplicates(
            [c.opts['filename'] for c in self.stack.childs])

    def layerIndex(self, filename, layername):
        for n, ch in enumerate(self.stack.childs):
            if ch.opts['filename'] == filename and ch.opts[
                    'layername'] == layername:
                return n
        return None

    def updateInput(self):
        '''
        Update the input coming from file
        '''
        self._readFiles(self.filenames, self._updateFiles)

    def _updateFiles(self, data, fnames, labels):
        old_fnames = [c.opts['filename'] for c in self.stack.childs]
        old_labels = [c.opts['layername'] for c in self.stack.childs]
        changes = 'reloaded at ' + time.strftime("%c")

        if fnames == old_fnames and labels == old_labels:
            self.changeAllLayers(data, changes=changes, backup=True)
        else:
            #layers cannot be easily exchanged, so:
            for d, f, l in zip(data, fnames, labels):
                index = self.layerIndex(f, l)
                if index is not None:
                    self.changeLayer(d,
                                     changes='reloaded at ' +
                                     time.strftime("%c"),
                                     index=index)
                else:
                    #TODO: insert layer behind last filename layer
                    self.addLayer(filename=f, label=l, data=d)

    def addLayers(self, datas, fnames, labels=None, **kwargs):
        if labels is None:
            labels = [None] * len(fnames)
        for l, f, d in zip(labels, fnames, datas):
            self.addLayer(data=d, filename=f, label=l, **kwargs)

    def addFiles(self, fnames, openfiles=True):
        '''
        Add input from file(s) to the stack
        -> read input
        -> add layer
        '''
        ff = self.filenames
        for f in list(fnames):
            if f in ff:
                print "file '%s' already in display '%s'" % (f, self.name())
                #fnames.remove(f)
        if fnames:
            if not self.reader:
                self.reader = getFileReader(fnames)
                self.reader = self.reader(self)
            if openfiles:
                self._readFiles(fnames, self.addLayers)
            else:
                d = [None] * len(fnames)
                self.addLayers(d, fnames, d)

    def saveState(self):
        state = {}
        #         path += ('display',str(self.number))
        #layers
        state['stack'] = self.stack.saveState()
        #automation
        state['automation'] = self.tab.automation.saveState()
        #parameters
        state['parameters'] = self.p.saveState()
        #         session.addContentToSave(self.p.saveState(), *path+('parameters.txt',))
        #dock
        state['dock'] = self.label.maximized
        #         session.addContentToSave(self.label.maximized, *path+('dock.txt',))
        #to init the current toolbars:
        self.clicked.emit(self)
        #widget
        state['widget'] = self.widget.saveState()
        return state

    @property
    def tools(self):
        return self.widget.tools

    def restoreState(self, state):
        #layers
        self.stack.restoreState(state['stack'])
        #automation
        self.tab.automation.restoreState(state['automation'])
        #parameters
        #TODO: this is not clean - stack is mentioned above and already restore its parameters...
        self.stack._valuesChanged()
        self.p.restoreState(state['parameters'])
        #widget
        self.widget.restoreState(state['widget'])
        #dock
        if state['dock']:
            self.maximize()

    def openFilesFunctions(self):
        return [lambda f=f: self.reader.open(f)[0] for f in self.filenames]

    def _readFiles(self, filenames, dataFunction):
        try:
            self.reader.done.disconnect()
        except TypeError:
            pass  # nothing connected so far
        self.reader.done.connect(dataFunction)
        self.reader.start(filenames)
예제 #22
0
    def _intersectionPointsAndAngles(r, ratioEllispeRectangle):
        '''
        return all 8  x and y coords of lines build by intersection of ellipse and rect
        '''
        w = r.width()
        h = r.height()
        x1 = 0.5 * w
        y2 = 0.5 * h

        #ellipse parameters:
        a = x1 * ratioEllispeRectangle
        b = y2 * ratioEllispeRectangle
        #intersection coords in the 1st quadrant with center=(0,0):
        y1 = ((1 - x1**2 / a**2) * b**2)**0.5
        x2 = ((1 - y2**2 / b**2) * a**2)**0.5

        c = r.center()
        cx = c.x()
        cy = c.y()

        #edge points:
        p1 = QtCore.QPointF(cx + x1, cy + y1)
        p2 = QtCore.QPointF(cx + x2, cy + y2)
        p3 = QtCore.QPointF(cx - x2, cy + y2)
        p4 = QtCore.QPointF(cx - x1, cy + y1)
        p5 = QtCore.QPointF(cx - x1, cy - y1)
        p6 = QtCore.QPointF(cx - x2, cy - y2)
        p7 = QtCore.QPointF(cx + x2, cy - y2)
        p8 = QtCore.QPointF(cx + x1, cy - y1)

        #angle in as degree*16 (needed in .drawArc)
        a1 = int(QtCore.QLineF(c, p1).angle() * 16)
        a2 = int(QtCore.QLineF(c, p2).angle() * 16)
        a4 = int(QtCore.QLineF(c, p4).angle() * 16)
        a6 = int(QtCore.QLineF(c, p6).angle() * 16)
        a8 = int(QtCore.QLineF(c, p8).angle() * 16)

        arc_length = a1 - a2
        return (p1, p2, p3, p4, p5, p6, p7, p8), (a2, a4, a6, a8), arc_length
예제 #23
0
 def painterPath(self):
     p = self.state['pos']
     s = self.state['size']
     path = QPainterPath()
     path.addEllipse(QtCore.QRectF(p[0], p[1], s[0], s[1]))
     return path
예제 #24
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.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)
예제 #25
0
    def _appendMenubarAndPreferences(self):
        m = self.menuBar()
        m.setFixedHeight(25)
        #         m.setMaximumHeight(25)

        m.aboutWidget.setModule(dataArtist)
        m.aboutWidget.setInstitutionLogo(
            MEDIA_FOLDER.join('institution_logo.svg'))

        #hide the menu so toolbars can only be show/hidden via gui->view->toolbars:
        m.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)

        self.undoRedo = UndoRedo(MEDIA_FOLDER)

        self.gTools = GlobalTools()
        self.gTools.addWidget(self.undoRedo)

        m.setCornerWidget(self.gTools)

        #APPEND PREFERENCES
        t = m.file_preferences.tabs
        t.addTab(PreferencesView(self), 'View')
        t.addTab(self.pref_import, 'Import')
        t.addTab(PreferencesCommunication(self), 'Communication')
        #APPEND MENUBAR
        #MENU - FILE
        f = m.menu_file
        p = f.action_preferences
        action_file = QtGui.QAction('&Import', f)
        action_file.triggered.connect(self.openFile)
        action_file.setShortcut(
            QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_I))
        f.insertAction(p, action_file)
        f.insertSeparator(p)
        #MENU VIEW
        v = m.menu_view
        #ACTION PRINT VIEW
        aPrintView = QtGui.QAction('Print view', v)
        aPrintView.setCheckable(True)
        aPrintView.triggered.connect(
            lambda checked: self.currentWorkspace().setPrintView(checked))
        v.addAction(aPrintView)

        #SHOW/HIDE history
        aHistory = QtGui.QAction('Program history', v)
        aHistory.setShortcut(QtCore.Qt.Key_F4)

        aHistory.setCheckable(True)

        def showhideHistory(checked):
            s = self.currentWorkspace().middle_splitter
            r = s.getRange(1)[1]
            if checked:
                r /= 1.5
            return s.moveSplitter(r, 1)

        def isHistoryVisible():
            s = self.currentWorkspace().middle_splitter
            aHistory.setChecked(s.sizes()[1] != 0)

        aHistory.triggered.connect(showhideHistory)
        v.aboutToShow.connect(isHistoryVisible)
        v.addAction(aHistory)

        #SHOW/HIDE preferences
        aPref = QtGui.QAction('Dock preferences', v)
        aPref.setShortcut(QtCore.Qt.Key_F3)
        aPref.setCheckable(True)

        def showhidePref(checked):
            s = self.currentWorkspace().vert_splitter
            r = s.getRange(1)[1]
            if checked:
                r /= 3
            else:
                r = 0
            return s.moveSplitter(r, 1)

        def isPrefVisible():
            w = self.currentWorkspace()
            s = w.vert_splitter
            aPref.setChecked(s.sizes()[0] != 0)
            aPref.setEnabled(w.displayPrefTabs.isVisible())

        aPref.triggered.connect(showhidePref)
        v.aboutToShow.connect(isPrefVisible)
        v.addAction(aPref)

        #ACTION VIEW2CLIPBOARD
        aClipboard = QtGui.QAction('Copy view to clipboard', v)
        aClipboard.triggered.connect(
            lambda checked: self.currentWorkspace().copyViewToClipboard())
        v.addAction(aClipboard)
        #ACTION Display2CLIPBOARD
        aClipboard = QtGui.QAction('Copy active display to clipboard', v)
        aClipboard.triggered.connect(lambda checked: self.currentWorkspace().
                                     copyCurrentDisplayToClipboard())
        v.addAction(aClipboard)
        #MENU - TOOLS
        t = m.menu_tools = QtGui.QMenu('Dock')
        m.insertMenuBefore(m.menu_workspace, t)
        #ADD DISPLAY
        mDisplay = t.addMenu('Add Display')
        for i, name in (  #(1, 'Dot'), 
            (2, 'Graph'),
            (3, 'Image/Video'),
                #(4, 'Surface')
                #TODO:
                #(4, 'TODO: Surface'),
                #(5, 'TODO: Volume')
        ):
            mDisplay.addAction('%sD - %s' % (i - 1, name)).triggered.connect(
                lambda checked, i=i: self.currentWorkspace().addDisplay(axes=i
                                                                        ))
        #ADD TABLE
        t.addAction('Add Table').triggered.connect(
            lambda: self.currentWorkspace().addTableDock())
        #ADD NOTEPAD
        t.addAction('Add Notepad').triggered.connect(
            lambda: self.currentWorkspace().addTextDock())
        t.addSeparator()
        #DUPLICATE CURRENT DOCK
        t.addAction('Duplicate current display').triggered.connect(
            self._duplicateCurrentDiplay)
        self._m_duplDisp = t.addMenu('Move current display to other workspace')
        self._m_duplDisp.aboutToShow.connect(self._fillMenuDuplicateToOtherWS)
        #MENU - TOOLBARS
        self.menu_toolbars = QtGui.QMenu('Toolbars', m)
        self.connect(self.menu_toolbars,
                     QtCore.SIGNAL("hovered(QAction *)"),
                     lambda action, m=self.menu_toolbars:
                     _showActionToolTipInMenu(m, action))

        #SHOW ALL TOOLBARS - ACTION
        a = self.menu_toolbars.a_show = QtGui.QAction('show', m)
        f = a.font()
        f.setBold(True)
        a.setFont(f)
        a.setCheckable(True)
        a.setChecked(True)
        a.triggered.connect(self._toggleShowSelectedToolbars)

        self.menu_toolbars.aboutToShow.connect(self._listToolbarsInMenu)
        m.insertMenuBefore(m.menu_workspace, self.menu_toolbars)
        #MENU HELP
        m.menu_help.addAction('User manual').triggered.connect(
            lambda checked: os.startfile(HELP_FILE))
        #TUTORIALS
        ####not used at the moment
        #         self.m_tutorials = TutorialMenu(
        #                         tutorialFolder=PathStr.getcwd('dataArtist').join('tutorials'),
        #                         openFunction=self._openFnForTutorial,
        #                         saveFunction=self.app.session.blockingSave)
        #         m.menu_help.addMenu(self.m_tutorials)

        m.menu_help.addAction('Online tutorials').triggered.connect(
            lambda checked: os.startfile(
                'http://www.youtube.com/channel/UCjjngrC3jPdx1HL8zJ8yqLQ'))
        m.menu_help.addAction('Support').triggered.connect(
            lambda checked: os.startfile(
                'https://github.com/radjkarl/dataArtist/issues'))
예제 #26
0
 def setCircle(self, _dx, dy):
     n = self.nCells[1]
     o = max(0, 2 * (dy - (0.5 / n)))
     return self.setCircleOffs(QtCore.QSizeF(0, o))
예제 #27
0
    def open(self, filename):

        prefs = self.preferences
        #VARIABLES:
        buff = prefs.pBuffer.value()
        step = prefs.pReadEveryNLine.value()
        stop_at_line = prefs.pHasStopLine.value()
        stop_n = prefs.pStopLine.value()
        x_col = prefs.pXColumn.value()
        has_x_col = prefs.pHasXColumn.value()

        self.n_line = 0  #number of current line
        step_len = 0  #number of lines in the read file_part
        n_defective_lines = 0  # number of corrupted lines
        i = 0  # current index in data array
        at_end = False  # is file the the end

        labels = filename

        #COUNT LINES:
        if stop_at_line:
            self.nLines = stop_n
        else:
            modified = QtCore.QFileInfo(filename).lastModified().toString()
            #ONLY OF THIS IS A NEW FILE OR THE FILE WAS MODIFIED:
            if not (self._lastFilename == filename
                    and self._lastModified == modified):
                self.nLines = countLines(filename, prefs.pBuffer.value())
                self._lastnLines = self.nLines
                self._lastFilename = filename
                self._lastModified = modified
            else:
                self.nLines = self._lastnLines

        #GET NUMBER OF COLUMNS:
        with open(filename, 'r') as f:

            #FIND SEPARATOR:
            if prefs.pFindSeparator.value():
                prefs.pSeparator.setValue(self._findSeparator(f))
            separator = prefs.separators[prefs.pSeparator.value()]

            #DEFINE NUMBER OF COLUMNS:
            n_col = f.readline().count(separator) + 1
            f.seek(0)  #back to begin
            #FILTER COLUMNS:
            filter_columns = prefs.pFilterColumns.value()
            if filter_columns:
                c = [ch.value()
                     for ch in prefs.pFilterColumns.children()[1:]][:n_col]
                #ADD X COLUMN TO THE BEGINNING:
                if has_x_col:
                    if x_col not in c:
                        c.insert(0, x_col)
                n_col = len(c)
                col_filter = itemgetter(*c)
            elif n_col > 1:
                col_filter = lambda l: l[:n_col]
            else:
                col_filter = lambda l: l[0]

            #GET FIRST LINE NAMES:
            fline = prefs.pFirstLine.value()
            if fline != '-':
                names = col_filter(f.readline().split(separator))
                if fline == 'axes names':
                    for n, ax in enumerate(self.display.axes):
                        ax.p.setValue(names[n])

                else:  #plot names:
                    labels = names
                    if has_x_col:
                        labels.pop(x_col)

            #JUMP TO START POSITION:
            startline = prefs.pStartLine.value()
            if startline:
                f.readline(startline)
                self.n_line = startline

            #PRINT FIRST 10 LINES:
            if prefs.pPrintFirstLines.value():
                startPos = f.tell()
                print '=========='
                for line in f.readlines(min(self.nLines, 10)):

                    #TODO: do the check for \n only once
                    # ??? doesn't have every line \n at the end??
                    #print line[-2:]
                    #if line[-2:] == '\n':
                    #    line = line[:-2]
                    print '[%s]: %s' % (self.n_line, line)
                    print '--> %s\n' % str(col_filter(line.split(separator)))
                f.seek(startPos)
                print '=========='

            #CREATE DATA ARRAY:
            shape = self.nLines / step
            if n_col == 0:
                raise Exception('no columns given')
            elif n_col > 1:
                shape = (shape, n_col)
            data = np.empty(shape=shape,
                            dtype=prefs.dtypes[prefs.pDType.value()])

            #MAIN LOOP:
            while not self.canceled:
                #READ PART OF THE FILE:
                file_piece = f.readlines(buff)
                l = len(file_piece)
                if not l:
                    break
                for n, line in enumerate(file_piece[::step]):
                    #line = line[:-1]
                    #FILTER COLUMNS:
                    line = col_filter(line.split(separator))
                    self.n_line = n + step_len
                    #ADD LINE TO ARRAY:
                    try:
                        data[i] = line
                        i += 1
                    except ValueError:
                        n_defective_lines += 1
                #CHECK BREAK CRITERIA:
                    if stop_at_line and self.n_line >= stop_n:
                        at_end = True
                        break
                if at_end:
                    break
                step_len += l
            data = data[:i]
            print '%s lines were corrupted' % n_defective_lines

            #SPLIT ARRAY IF NEEDED:
            if (has_x_col and n_col > 2) or (not has_x_col and n_col > 1):
                if has_x_col:
                    x = data[:, x_col]
                    #GET Y COLUMNS THROUGH REMOVING THE X COLUMN:
                    y_cols = np.c_[data[:, :x_col], data[:, x_col + 1:]]
                else:
                    y_cols = data
                l = []
                #CREATE TUPLE OF [y_n] OR [x, y_n] arrays:
                for n in range(y_cols.shape[1]):
                    y = y_cols[:, n]
                    if has_x_col:
                        y = np.c_[x, y]
                    l.append(y)
                return tuple(l), labels
            return [data], labels
예제 #28
0
 def homography(self):
     t = QtGui.QTransform()
     poly = QtGui.QPolygonF([QtCore.QPointF(*v) for v in self.vertices()])
     QtGui.QTransform.squareToQuad(poly, t)
     self._homography = t
     return t