def __init__(self, topLevelOperator, projectFileGroupName):
        super(DataSelectionSerializer, self).__init__(projectFileGroupName)
        self.topLevelOperator = topLevelOperator
        self._dirty = False

        self._projectFilePath = None

        self.version = "0.2"

        def handleDirty():
            if not self.ignoreDirty:
                self._dirty = True

        self.topLevelOperator.ProjectFile.notifyDirty(bind(handleDirty))
        self.topLevelOperator.ProjectDataGroup.notifyDirty(bind(handleDirty))
        self.topLevelOperator.WorkingDirectory.notifyDirty(bind(handleDirty))

        def handleNewDataset(slot, roleIndex):
            slot[roleIndex].notifyDirty(bind(handleDirty))
            slot[roleIndex].notifyDisconnect(bind(handleDirty))

        def handleNewLane(multislot, laneIndex):
            assert multislot == self.topLevelOperator.DatasetGroup
            multislot[laneIndex].notifyInserted(bind(handleNewDataset))
            for roleIndex in range(len(multislot[laneIndex])):
                handleNewDataset(multislot[laneIndex], roleIndex)

        self.topLevelOperator.DatasetGroup.notifyInserted(bind(handleNewLane))

        # If a dataset was removed, we need to be reserialized.
        self.topLevelOperator.DatasetGroup.notifyRemoved(bind(handleDirty))
Example #2
0
    def initAppletDrawerUi(self):
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir+"/drawer.ui")
        
        layout = QVBoxLayout()
        layout.setSpacing(0)
        self._drawer.setLayout( layout )

        thresholdWidget = ThresholdingWidget(self)
        thresholdWidget.valueChanged.connect( self.handleThresholdGuiValuesChanged )
        self._drawer.layout().addWidget( thresholdWidget )
        self._drawer.layout().addSpacerItem( QSpacerItem(0,0,vPolicy=QSizePolicy.Expanding) )
        
        def updateDrawerFromOperator():
            minValue, maxValue = (0,255)

            if self.topLevelOperatorView.MinValue.ready():
                minValue = self.topLevelOperatorView.MinValue.value
            if self.topLevelOperatorView.MaxValue.ready():
                maxValue = self.topLevelOperatorView.MaxValue.value

            thresholdWidget.setValue(minValue, maxValue)
            
        self.topLevelOperatorView.MinValue.notifyDirty( bind(updateDrawerFromOperator) )
        self.topLevelOperatorView.MaxValue.notifyDirty( bind(updateDrawerFromOperator) )
        updateDrawerFromOperator()
    def __init__(self, parent=None, graph=None):
        self._solver = "ILP"
        super(OpStructuredTracking, self).__init__(parent=parent, graph=graph)

        self.labels = {}
        self.divisions = {}
        self.Annotations.setValue({})
        self._ndim = 3

        self._parent = parent

        self.DivisionWeight.setValue(0.6)
        self.DetectionWeight.setValue(0.6)
        self.TransitionWeight.setValue(0.01)
        self.AppearanceWeight.setValue(0.3)
        self.DisappearanceWeight.setValue(0.2)

        self.MaxNumObjOut.setValue(1)

        self.transition_parameter = 5
        self.detectionWeight = 1
        self.divisionWeight = 1
        self.transitionWeight = 1
        self.appearanceWeight = 1
        self.disappearanceWeight = 1

        self.Crops.notifyReady(bind(self._updateCropsFromOperator) )
        self.Labels.notifyReady( bind(self._updateLabelsFromOperator) )
        self.Divisions.notifyReady( bind(self._updateDivisionsFromOperator) )

        self._solver = self.parent.parent._solver
    def __init__(self, mainOperator, projectFileGroupName):
        with Tracer(traceLogger):
            super(AutocontextClassificationSerializer,
                  self).__init__(projectFileGroupName)
            self.mainOperator = mainOperator
            self._initDirtyFlags()

            # Set up handlers for dirty detection
            def handleDirty(section):
                if not self.ignoreDirty:
                    self._dirtyFlags[section] = True

            def handleNewClassifier(slot, index):
                slot[index].notifyDirty(bind(handleDirty, 1))

            #self.mainOperator.Classifiers.notifyDirty( bind(handleDirty, Section.Classifiers) )
            self.mainOperator.Classifiers.notifyInserted(
                bind(handleNewClassifier))

            def handleNewImage(section, slot, index):
                slot[index].notifyDirty(bind(handleDirty, section))
                # New label images need to be 'serialized' as an empty group.
                if section == Section.Labels:
                    handleDirty(Section.Labels)

            # These are multi-slots, so subscribe to dirty callbacks on each of their subslots as they are created
            self.mainOperator.LabelImages.notifyInserted(
                bind(handleNewImage, Section.Labels))
            self.mainOperator.PredictionProbabilities.notifyInserted(
                bind(handleNewImage, Section.Predictions))
            #self.mainOperator.PixelOnlyPredictions.notifyInserted( bind(handleNewImage, Section.PixelPredictions) )

            self._predictionStorageEnabled = False
            self._predictionStorageRequest = None
            self._predictionsPresent = False
Example #5
0
    def initAppletDrawerUi(self):
        with Tracer(traceLogger):
            # Load the ui file (find it in our own directory)
            localDir = os.path.split(__file__)[0]
            self._drawer = uic.loadUi(localDir+"/drawer.ui")
            
            layout = QVBoxLayout( self )
            layout.setSpacing(0)
            self._drawer.setLayout( layout )
    
            thresholdWidget = ThresholdingWidget(self)
            thresholdWidget.valueChanged.connect( self.handleThresholdGuiValuesChanged )
            layout.addWidget( thresholdWidget )
            
            def updateDrawerFromOperator():
                minValue, maxValue = (0,255)

                if self.mainOperator.MinValue.ready():
                    minValue = self.mainOperator.MinValue.value
                if self.mainOperator.MaxValue.ready():
                    maxValue = self.mainOperator.MaxValue.value

                thresholdWidget.setValue(minValue, maxValue)                
                
            self.mainOperator.MinValue.notifyDirty( bind(updateDrawerFromOperator) )
            self.mainOperator.MaxValue.notifyDirty( bind(updateDrawerFromOperator) )
    def __init__(self, mainOperator, projectFileGroupName):
        with Tracer(traceLogger):
            super(PixelClassificationSerializer,
                  self).__init__(projectFileGroupName, self.SerializerVersion)
            self.mainOperator = mainOperator
            self._initDirtyFlags()

            # Set up handlers for dirty detection
            def handleDirty(section):
                self._dirtyFlags[section] = True

            self.mainOperator.Classifier.notifyDirty(
                bind(handleDirty, Section.Classifier))

            def handleNewImage(section, slot, index):
                slot[index].notifyDirty(bind(handleDirty, section))

            # These are multi-slots, so subscribe to dirty callbacks on each of their subslots as they are created
            self.mainOperator.LabelImages.notifyInserted(
                bind(handleNewImage, Section.Labels))
            self.mainOperator.PredictionProbabilities.notifyInserted(
                bind(handleNewImage, Section.Predictions))

            self._predictionStorageEnabled = False
            self._predictionStorageRequest = None
            self._predictionsPresent = False
Example #7
0
 def __init__(self, dataSelectionOperator, serializer, guiControlSignal, guiMode=GuiMode.Normal):
     with Tracer(traceLogger):
         super(DataSelectionGui, self).__init__()
 
         self.drawer = None
         self.mainOperator = dataSelectionOperator
         self.guiMode = guiMode
         self.serializer = serializer
         self.guiControlSignal = guiControlSignal
         self.threadRouter = ThreadRouter(self)
         
         self.initAppletDrawerUic()
         self.initCentralUic()
 
         def handleNewDataset( multislot, index ):
             with Tracer(traceLogger):
                 assert multislot == self.mainOperator.Dataset
                 # Make room in the table
                 self.fileInfoTableWidget.insertRow( index )
                 
                 # Update the table row data when this slot has new data
                 # We can't bind in the row here because the row may change in the meantime.
                 self.mainOperator.Dataset[index].notifyDirty( self.updateTableForSlot )
 
         self.mainOperator.Dataset.notifyInserted( bind( handleNewDataset ) )
     
         def handleDatasetRemoved( multislot, index ):
             with Tracer(traceLogger):
                 assert multislot == self.mainOperator.Dataset
                 
                 # Simply remove the row we don't need any more
                 self.fileInfoTableWidget.removeRow( index )
 
         self.mainOperator.Dataset.notifyRemove( bind( handleDatasetRemoved ) )
Example #8
0
    def setImageNameListSlot(self, multiSlot):
        assert multiSlot.level == 1
        self.imageNamesSlot = multiSlot

        def insertImageName(index, slot):
            self.imageSelectionCombo.setItemText(index, slot.value)
            if self.currentImageIndex == -1:
                self.changeCurrentInputImageIndex(index)

        def handleImageNameSlotInsertion(multislot, index):
            assert multislot == self.imageNamesSlot
            self.populatingImageSelectionCombo = True
            self.imageSelectionCombo.insertItem(index, "uninitialized")
            self.populatingImageSelectionCombo = False
            multislot[index].notifyDirty(bind(insertImageName, index))

        multiSlot.notifyInserted(bind(handleImageNameSlotInsertion))

        def handleImageNameSlotRemoval(multislot, index):
            # Simply remove the combo entry, which causes the currentIndexChanged signal to fire if necessary.
            self.imageSelectionCombo.removeItem(index)
            if len(multislot) == 0:
                self.changeCurrentInputImageIndex(-1)

        multiSlot.notifyRemove(bind(handleImageNameSlotRemoval))
    def __init__(self, parent=None, graph=None):
        super(OpStructuredTracking, self).__init__(parent=parent, graph=graph)

        self.labels = {}
        self.divisions = {}
        self.Annotations.setValue({})
        self._ndim = 3

        self._parent = parent

        self.DivisionWeight.setValue(0.6)
        self.DetectionWeight.setValue(0.6)
        self.TransitionWeight.setValue(0.01)
        self.AppearanceWeight.setValue(0.3)
        self.DisappearanceWeight.setValue(0.2)

        self.MaxNumObjOut.setValue(1)

        self.transition_parameter = 5
        self.detectionWeight = 1
        self.divisionWeight = 1
        self.transitionWeight = 1
        self.appearanceWeight = 1
        self.disappearanceWeight = 1

        self.Crops.notifyReady(bind(self._updateCropsFromOperator) )
        self.Labels.notifyReady( bind(self._updateLabelsFromOperator) )
        self.Divisions.notifyReady( bind(self._updateDivisionsFromOperator) )
    def __init__(self, op, shellRequestSignal, guiControlSignal):
        # Tell our base class which slots to monitor
        labelSlots = LabelingGui.LabelingSlots()
        labelSlots.labelInput = op.LabelInputs
        labelSlots.labelOutput = op.LabelImages

        labelSlots.labelEraserValue = op.Eraser
        labelSlots.labelDelete = op.DeleteLabel

        labelSlots.maxLabelValue = op.NumLabels
        labelSlots.labelsAllowed = op.LabelsAllowedFlags

        # We provide our own UI file (which adds an extra control for
        # interactive mode) This UI file is copied from
        # pixelClassification pipeline
        #
        labelingDrawerUiPath = os.path.split(__file__)[0] + '/labelingDrawer.ui'

        # Base class init
        super(ObjectClassificationGui, self).__init__(labelSlots, op,
                                                      labelingDrawerUiPath,
                                                      crosshair=False)

        self.op = op
        self.guiControlSignal = guiControlSignal
        self.shellRequestSignal = shellRequestSignal

        topLevelOp = self.topLevelOperatorView.viewed_operator()
        self.threadRouter = ThreadRouter(self)
        op.Warnings.notifyDirty(self.handleWarnings)

        # unused
        self.labelingDrawerUi.savePredictionsButton.setEnabled(False)
        self.labelingDrawerUi.savePredictionsButton.setVisible(False)

        self.labelingDrawerUi.brushSizeComboBox.setEnabled(False)
        self.labelingDrawerUi.brushSizeComboBox.setVisible(False)
        
        self.labelingDrawerUi.brushSizeCaption.setVisible(False)

        self._colorTable16_forpmaps = self._createDefault16ColorColorTable()
        self._colorTable16_forpmaps[15] = QColor(Qt.black).rgba() #for objects with NaNs in features

        # button handlers
        self._interactiveMode = False
        self._showPredictions = False
        self._labelMode = True

        self.labelingDrawerUi.subsetFeaturesButton.clicked.connect(
            self.handleSubsetFeaturesClicked)
        self.labelingDrawerUi.checkInteractive.toggled.connect(
            self.handleInteractiveModeClicked)
        self.labelingDrawerUi.checkShowPredictions.toggled.connect(
            self.handleShowPredictionsClicked)

        # enable/disable buttons logic
        self.op.ObjectFeatures.notifyDirty(bind(self.checkEnableButtons))
        self.op.NumLabels.notifyDirty(bind(self.checkEnableButtons))
        self.op.SelectedFeatures.notifyDirty(bind(self.checkEnableButtons))
        self.checkEnableButtons()
Example #11
0
    def __init__(self,
                 parentApplet,
                 croppingSlots,
                 topLevelOperatorView,
                 drawerUiPath=None,
                 rawInputSlot=None,
                 crosshair=True):
        """
        Constructor.

        :param croppingSlots: Provides the slots needed for sourcing/sinking crop data.  See CroppingGui.CroppingSlots
                              class source for details.
        :param topLevelOperatorView: is provided to the LayerViewerGui (the base class)
        :param drawerUiPath: can be given if you provide an extended drawer UI file.  Otherwise a default one is used.
        :param rawInputSlot: Data from the rawInputSlot parameter will be displayed directly underneath the elements
                             (if provided).
        """

        # Do we have all the slots we need?
        assert isinstance(croppingSlots, CroppingGui.CroppingSlots)
        assert croppingSlots.cropInput is not None, "Missing a required slot."
        assert croppingSlots.cropOutput is not None, "Missing a required slot."
        assert croppingSlots.cropEraserValue is not None, "Missing a required slot."
        assert croppingSlots.cropDelete is not None, "Missing a required slot."
        assert croppingSlots.cropNames is not None, "Missing a required slot."
        assert croppingSlots.cropsAllowed is not None, "Missing a required slot."

        self.__cleanup_fns = []
        self._croppingSlots = croppingSlots
        self._minCropNumber = 0
        self._maxCropNumber = 99  #100 or 255 is reserved for eraser

        self._rawInputSlot = rawInputSlot

        self.topLevelOperatorView.Crops.notifyDirty(bind(self._updateCropList))
        self.topLevelOperatorView.Crops.notifyDirty(bind(self._updateCropList))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.Crops.unregisterDirty,
                    bind(self._updateCropList)))

        self._colorTable16 = self._createDefault16ColorColorTable()
        self._programmaticallyRemovingCrops = False

        self._initCropUic(drawerUiPath)

        self._maxCropNumUsed = 0

        self._allowDeleteLastCropOnly = False
        self.__initShortcuts()
        # Init base class
        super(CroppingGui, self).__init__(
            parentApplet,
            topLevelOperatorView,
            [croppingSlots.cropInput, croppingSlots.cropOutput],
            crosshair=crosshair)
        self._croppingSlots.cropEraserValue.setValue(
            self.editor.brushingModel.erasingNumber)

        # Register for thunk events (easy UI calls from non-GUI threads)
        self.thunkEventHandler = ThunkEventHandler(self)
    def __init__(self, mainOperator, projectFileGroupName):
        with Tracer(traceLogger):
            super( AutocontextClassificationSerializer, self ).__init__( projectFileGroupName  )
            self.mainOperator = mainOperator
            self._initDirtyFlags()
   
            # Set up handlers for dirty detection
            def handleDirty(section):
                if not self.ignoreDirty:
                    self._dirtyFlags[section] = True

            def handleNewClassifier(slot, index):
                slot[index].notifyDirty( bind(handleDirty, 1))
    
            #self.mainOperator.Classifiers.notifyDirty( bind(handleDirty, Section.Classifiers) )
            self.mainOperator.Classifiers.notifyInserted( bind(handleNewClassifier))
            
            def handleNewImage(section, slot, index):
                slot[index].notifyDirty( bind(handleDirty, section) )
                # New label images need to be 'serialized' as an empty group.
                if section == Section.Labels:
                    handleDirty(Section.Labels)
    
            # These are multi-slots, so subscribe to dirty callbacks on each of their subslots as they are created
            self.mainOperator.LabelImages.notifyInserted( bind(handleNewImage, Section.Labels) )
            self.mainOperator.PredictionProbabilities.notifyInserted( bind(handleNewImage, Section.Predictions) )
            #self.mainOperator.PixelOnlyPredictions.notifyInserted( bind(handleNewImage, Section.PixelPredictions) )
            

            self._predictionStorageEnabled = False
            self._predictionStorageRequest = None
            self._predictionsPresent = False
    def __init__(self, topLevelOperator, projectFileGroupName):
        super( DataSelectionSerializer, self ).__init__(projectFileGroupName)
        self.topLevelOperator = topLevelOperator
        self._dirty = False
        self.caresOfHeadless = True
        
        self._projectFilePath = None
        
        self.version = '0.2'
        
        def handleDirty():
            if not self.ignoreDirty:
                self._dirty = True

        self.topLevelOperator.ProjectFile.notifyDirty( bind(handleDirty) )
        self.topLevelOperator.ProjectDataGroup.notifyDirty( bind(handleDirty) )
        self.topLevelOperator.WorkingDirectory.notifyDirty( bind(handleDirty) )
        
        def handleNewDataset(slot, roleIndex):
            slot[roleIndex].notifyDirty( bind(handleDirty) )
            slot[roleIndex].notifyDisconnect( bind(handleDirty) )
        def handleNewLane(multislot, laneIndex):
            assert multislot == self.topLevelOperator.DatasetGroup
            multislot[laneIndex].notifyInserted( bind(handleNewDataset) )
            for roleIndex in range( len(multislot[laneIndex]) ):
                handleNewDataset(multislot[laneIndex], roleIndex)
        self.topLevelOperator.DatasetGroup.notifyInserted( bind(handleNewLane) )

        # If a dataset was removed, we need to be reserialized.
        self.topLevelOperator.DatasetGroup.notifyRemoved( bind(handleDirty) )
Example #14
0
    def initAppletDrawerUi(self):
        """
        Reimplemented from LayerViewerGui base class.
        """
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir+"/drawer.ui")
        
        self._drawer.applyButton.clicked.connect( self._onApplyButtonClicked )
        self._drawer.tabWidget.currentChanged.connect( self._onTabCurrentChanged )

        self._sigmaSpinBoxes = { 'x' : self._drawer.sigmaSpinBox_X,
                                 'y' : self._drawer.sigmaSpinBox_Y,
                                 'z' : self._drawer.sigmaSpinBox_Z }

        self._allWatchedWidgets = self._sigmaSpinBoxes.values() + \
        [
            self._drawer.inputChannelSpinBox,
            self._drawer.lowThresholdSpinBox,
            self._drawer.highThresholdSpinBox,
            self._drawer.thresholdSpinBox,
            self._drawer.minSizeSpinBox,
            self._drawer.maxSizeSpinBox
        ]
        
        for widget in self._allWatchedWidgets:
            # If the user pressed enter inside a spinbox, auto-click "Apply"
            widget.installEventFilter( self )

        self._updateGuiFromOperator()
        self.topLevelOperatorView.InputImage.notifyReady( bind(self._updateGuiFromOperator) )
        self.topLevelOperatorView.InputImage.notifyMetaChanged( bind(self._updateGuiFromOperator) )
Example #15
0
    def __init__(self, parentApplet, topLevelOperatorView):
        """
        """
        self.topLevelOperatorView = topLevelOperatorView
        super(FeatureSelectionGui, self).__init__(parentApplet,
                                                  topLevelOperatorView,
                                                  crosshair=False)
        self.parentApplet = parentApplet

        self.__cleanup_fns = []

        self.topLevelOperatorView.SelectionMatrix.notifyDirty(
            bind(self.onFeaturesSelectionsChanged))
        self.topLevelOperatorView.FeatureListFilename.notifyDirty(
            bind(self.onFeaturesSelectionsChanged))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.SelectionMatrix.unregisterDirty,
                    bind(self.onFeaturesSelectionsChanged)))
        self.__cleanup_fns.append(
            partial(
                self.topLevelOperatorView.FeatureListFilename.unregisterDirty,
                bind(self.onFeaturesSelectionsChanged)))

        self.onFeaturesSelectionsChanged()

        # Init feature dialog
        self.initFeatureDlg()
Example #16
0
    def initAppletDrawerUi(self):
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir+"/drawer.ui")

        # If the user changes a setting the GUI, update the appropriate operator slot.        
        self._drawer.scalingFactorSpinBox.valueChanged.connect(self.updateOperatorScalingFactor)
        self._drawer.offsetSpinBox.valueChanged.connect(self.updateOperatorOffset)

        def updateDrawerFromOperator():
            scalingFactor, offset = (0,0)

            if self.topLevelOperatorView.ScalingFactor.ready():
                scalingFactor = self.topLevelOperatorView.ScalingFactor.value
            if self.topLevelOperatorView.Offset.ready():
                offset = self.topLevelOperatorView.Offset.value

            self._drawer.scalingFactorSpinBox.setValue(scalingFactor)
            self._drawer.offsetSpinBox.setValue(offset)

        # If the operator is changed *outside* the GUI (e.g. the project is loaded),
        #  then update the GUI to match the new operator slot values.            
        self.topLevelOperatorView.ScalingFactor.notifyDirty( bind(updateDrawerFromOperator) )
        self.topLevelOperatorView.Offset.notifyDirty( bind(updateDrawerFromOperator) )
        
        # Initialize the GUI with the operator's initial state.
        updateDrawerFromOperator()

        # Provide defaults if the operator isn't already configured.
        #  (e.g. if it's a blank project, then the operator won't have any setup yet.)
        if not self.topLevelOperatorView.ScalingFactor.ready():
            self.updateOperatorScalingFactor(1)
        if not self.topLevelOperatorView.Offset.ready():
            self.updateOperatorOffset(0)
Example #17
0
    def initAppletDrawerUi(self):
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir+"/drawer.ui")

        # If the user changes a setting the GUI, update the appropriate operator slot.        
        self._drawer.scalingFactorSpinBox.valueChanged.connect(self.updateOperatorScalingFactor)
        self._drawer.offsetSpinBox.valueChanged.connect(self.updateOperatorOffset)

        def updateDrawerFromOperator():
            scalingFactor, offset = (0,0)

            if self.topLevelOperatorView.ScalingFactor.ready():
                scalingFactor = self.topLevelOperatorView.ScalingFactor.value
            if self.topLevelOperatorView.Offset.ready():
                offset = self.topLevelOperatorView.Offset.value

            self._drawer.scalingFactorSpinBox.setValue(scalingFactor)
            self._drawer.offsetSpinBox.setValue(offset)

        # If the operator is changed *outside* the GUI (e.g. the project is loaded),
        #  then update the GUI to match the new operator slot values.            
        self.topLevelOperatorView.ScalingFactor.notifyDirty( bind(updateDrawerFromOperator) )
        self.topLevelOperatorView.Offset.notifyDirty( bind(updateDrawerFromOperator) )
        
        # Initialize the GUI with the operator's initial state.
        updateDrawerFromOperator()

        # Provide defaults if the operator isn't already configured.
        #  (e.g. if it's a blank project, then the operator won't have any setup yet.)
        if not self.topLevelOperatorView.ScalingFactor.ready():
            self.updateOperatorScalingFactor(1)
        if not self.topLevelOperatorView.Offset.ready():
            self.updateOperatorOffset(0)
 def __init__(self, dataSelectionOperator, guiControlSignal, progressSignal, title):
     with Tracer(traceLogger):
         super(BatchIoGui, self).__init__()
 
         self.title = title
         self.drawer = None
         self.mainOperator = dataSelectionOperator
         
         self.initAppletDrawerUic()
         self.initCentralUic()
         self.chosenExportDirectory = '/'
         
         self.guiControlSignal = guiControlSignal
         self.progressSignal = progressSignal
         
         def handleNewDataset( multislot, index ):
             # Make room in the GUI table
             self.tableWidget.insertRow( index )
             
             # Update the table row data when this slot has new data
             # We can't bind in the row here because the row may change in the meantime.
             multislot[index].notifyDirty( bind( self.updateTableForSlot ) )
 
         self.mainOperator.OutputDataPath.notifyInserted( bind( handleNewDataset ) )
         
         def handleDatasetRemoved( multislot, index ):
             # Simply remove the row we don't need any more
             self.tableWidget.removeRow( index )
 
         self.mainOperator.OutputDataPath.notifyRemove( bind( handleDatasetRemoved ) )
         
         self.mainOperator.Suffix.notifyDirty( self.updateDrawerGuiFromOperatorSettings )
         self.mainOperator.ExportDirectory.notifyDirty( self.updateDrawerGuiFromOperatorSettings )
         self.mainOperator.Format.notifyDirty( self.updateDrawerGuiFromOperatorSettings )
         self.updateDrawerGuiFromOperatorSettings()
Example #19
0
    def initAppletDrawerUi(self):
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir+"/drawer.ui")

        # If the user changes a setting the GUI, update the appropriate operator slot.        
        self._drawer.SuperPixelSizeSpinBox.valueChanged.connect(self.updateOperatorSuperPixelSize)
        self._drawer.CubenessSpinBox.valueChanged.connect(self.updateOperatorCubeness)
        self._drawer.MaxIterSpinBox.valueChanged.connect(self.updateOperatorMaxIter)

        def updateDrawerFromOperator():
            SuperPixelSize, Cubeness, MaxIter = (15,10, 6)

            if self.topLevelOperatorView.SuperPixelSize.ready():
                SuperPixelSize = self.topLevelOperatorView.SuperPixelSize.value

            if self.topLevelOperatorView.Cubeness.ready():
                Cubeness = self.topLevelOperatorView.Cubeness.value

            if self.topLevelOperatorView.MaxIter.ready():
                MaxIter = self.topLevelOperatorView.MaxIter.value

            self._drawer.SuperPixelSizeSpinBox.setValue(SuperPixelSize)
            self._drawer.CubenessSpinBox.setValue(Cubeness)
            self._drawer.MaxIterSpinBox.setValue(MaxIter)

        # If the operator is changed *outside* the GUI (e.g. the project is loaded),
        #  then update the GUI to match the new operator slot values.            
        self.topLevelOperatorView.SuperPixelSize.notifyDirty( bind(updateDrawerFromOperator))
        self.topLevelOperatorView.Cubeness.notifyDirty( bind(updateDrawerFromOperator))
        self.topLevelOperatorView.MaxIter.notifyDirty( bind(updateDrawerFromOperator))

        # Initialize the GUI with the operator's initial state.
        updateDrawerFromOperator()
Example #20
0
    def initAppletDrawerUi(self):
        localDir = os.path.split(__file__)[0]
        self._drawer = self._cropControlUi

        data_has_z_axis = True
        if self.topLevelOperatorView.InputImage.ready():
            tShape = self.topLevelOperatorView.InputImage.meta.getTaggedShape()
            if not 'z' in tShape or tShape['z']==1:
                data_has_z_axis = False

        self._cropControlUi._minSliderZ.setVisible(data_has_z_axis)
        self._cropControlUi._minSliderZ.setVisible(data_has_z_axis)
        self._cropControlUi._maxSliderZ.setVisible(data_has_z_axis)
        self._cropControlUi._minSpinZ.setVisible(data_has_z_axis)
        self._cropControlUi._maxSpinZ.setVisible(data_has_z_axis)
        self._cropControlUi.labelMinZ.setVisible(data_has_z_axis)
        self._cropControlUi.labelMaxZ.setVisible(data_has_z_axis)

        self._cropControlUi.AddCropButton.clicked.connect( bind (self.newCrop) )
        self._cropControlUi.SetCropButton.setVisible(False)
        self.editor.cropModel.mouseRelease.connect(bind(self.setCrop))

        self.topLevelOperatorView.MinValueT.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueT.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MinValueX.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueX.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MinValueY.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueY.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MinValueZ.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueZ.notifyDirty(self.apply_operator_settings_to_gui)

        self.topLevelOperatorView.InputImage.notifyDirty(self.setDefaultValues)
        self.topLevelOperatorView.PredictionImage.notifyDirty(self.setDefaultValues)

        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.addWidget( self._cropControlUi )
        layout.addSpacerItem( QSpacerItem(0,0,vPolicy=QSizePolicy.Expanding) )

        self.setDefaultValues()
        self.apply_operator_settings_to_gui()

        self.editor.showCropLines(True)
        self.editor.cropModel.setEditable (True)
        self.editor.cropModel.changed.connect(self.onCropModelChanged)
        self.editor.posModel.timeChanged.connect(self.updateTime)
        self._cropControlUi._minSliderT.valueChanged.connect(self._onMinSliderTMoved)
        self._cropControlUi._maxSliderT.valueChanged.connect(self._onMaxSliderTMoved)
        self._cropControlUi._minSliderX.valueChanged.connect(self._onMinSliderXMoved)
        self._cropControlUi._maxSliderX.valueChanged.connect(self._onMaxSliderXMoved)
        self._cropControlUi._minSliderY.valueChanged.connect(self._onMinSliderYMoved)
        self._cropControlUi._maxSliderY.valueChanged.connect(self._onMaxSliderYMoved)
        self._cropControlUi._minSliderZ.valueChanged.connect(self._onMinSliderZMoved)
        self._cropControlUi._maxSliderZ.valueChanged.connect(self._onMaxSliderZMoved)

        self._cropControlUi.cropListView.deleteCrop.connect(self.onDeleteCrop)
        self._cropControlUi.cropListView.colorsChanged.connect(self.onColorsChanged)

        self._initCropListView()
    def __init__(self, parentApplet, topLevelOperatorView):
        self.parentApplet = parentApplet
        # Tell our base class which slots to monitor
        labelSlots = LabelingGui.LabelingSlots()
        labelSlots.labelInput = topLevelOperatorView.LabelInputs
        labelSlots.labelOutput = topLevelOperatorView.LabelImages
        labelSlots.labelEraserValue = topLevelOperatorView.opLabelPipeline.opLabelArray.eraser
        labelSlots.labelDelete = topLevelOperatorView.opLabelPipeline.DeleteLabel
        labelSlots.labelNames = topLevelOperatorView.LabelNames
        labelSlots.labelsAllowed = topLevelOperatorView.LabelsAllowedFlags

        self.__cleanup_fns = []

        # We provide our own UI file (which adds an extra control for interactive mode)
        labelingDrawerUiPath = os.path.split(__file__)[0] + "/labelingDrawer.ui"

        # Base class init
        super(PixelClassificationGui, self).__init__(
            parentApplet, labelSlots, topLevelOperatorView, labelingDrawerUiPath
        )

        self.topLevelOperatorView = topLevelOperatorView

        self.interactiveModeActive = False
        # Immediately update our interactive state
        self.toggleInteractive(not self.topLevelOperatorView.FreezePredictions.value)

        self._currentlySavingPredictions = False

        self.labelingDrawerUi.liveUpdateButton.setEnabled(False)
        self.labelingDrawerUi.liveUpdateButton.setIcon(QIcon(ilastikIcons.Play))
        self.labelingDrawerUi.liveUpdateButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.labelingDrawerUi.liveUpdateButton.toggled.connect(self.toggleInteractive)

        self.topLevelOperatorView.LabelNames.notifyDirty(bind(self.handleLabelSelectionChange))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.LabelNames.unregisterDirty, bind(self.handleLabelSelectionChange))
        )

        self._initShortcuts()

        try:
            self.render = True
            self._renderedLayers = {}  # (layer name, label number)
            self._renderMgr = RenderingManager(renderer=self.editor.view3d.qvtk.renderer, qvtk=self.editor.view3d.qvtk)
        except:
            self.render = False

        # toggle interactive mode according to freezePredictions.value
        self.toggleInteractive(not self.topLevelOperatorView.FreezePredictions.value)

        def FreezePredDirty():
            self.toggleInteractive(not self.topLevelOperatorView.FreezePredictions.value)

        # listen to freezePrediction changes
        self.topLevelOperatorView.FreezePredictions.notifyDirty(bind(FreezePredDirty))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.FreezePredictions.unregisterDirty, bind(FreezePredDirty))
        )
Example #22
0
 def _handleLayerInsertion(self, slot, slotIndex):
     """
     The multislot providing our layers has a new item.
     Make room for it in the layer GUI and subscribe to updates.
     """
     # When the slot is ready, we'll replace the blank layer with real data
     slot[slotIndex].notifyReady( bind(self.updateAllLayers) )
     slot[slotIndex].notifyUnready( bind(self.updateAllLayers) )
Example #23
0
 def __init__(self, *args, **kwargs):
     super(CountingResultsViewer, self).__init__(*args, **kwargs)
     self.topLevelOperatorView.PmapColors.notifyDirty(
         bind(self.updateAllLayers))
     self.topLevelOperatorView.LabelNames.notifyDirty(
         bind(self.updateAllLayers))
     self.topLevelOperatorView.UpperBound.notifyDirty(
         bind(self.updateAllLayers))
Example #24
0
    def initAppletDrawerUi(self):
        localDir = os.path.split(__file__)[0]
        self._drawer = self._cropControlUi

        data_has_z_axis = True
        if self.topLevelOperatorView.InputImage.ready():
            tShape = self.topLevelOperatorView.InputImage.meta.getTaggedShape()
            if not 'z' in tShape or tShape['z']==1:
                data_has_z_axis = False

        self._cropControlUi._minSliderZ.setVisible(data_has_z_axis)
        self._cropControlUi._minSliderZ.setVisible(data_has_z_axis)
        self._cropControlUi._maxSliderZ.setVisible(data_has_z_axis)
        self._cropControlUi._minSpinZ.setVisible(data_has_z_axis)
        self._cropControlUi._maxSpinZ.setVisible(data_has_z_axis)
        self._cropControlUi.labelMinZ.setVisible(data_has_z_axis)
        self._cropControlUi.labelMaxZ.setVisible(data_has_z_axis)

        self._cropControlUi.AddCropButton.clicked.connect( bind (self.newCrop) )
        self._cropControlUi.SetCropButton.clicked.connect( bind (self.setCrop) )

        self.topLevelOperatorView.MinValueT.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueT.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MinValueX.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueX.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MinValueY.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueY.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MinValueZ.notifyDirty(self.apply_operator_settings_to_gui)
        self.topLevelOperatorView.MaxValueZ.notifyDirty(self.apply_operator_settings_to_gui)

        self.topLevelOperatorView.InputImage.notifyDirty(self.setDefaultValues)
        self.topLevelOperatorView.PredictionImage.notifyDirty(self.setDefaultValues)

        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.addWidget( self._cropControlUi )
        layout.addSpacerItem( QSpacerItem(0,0,vPolicy=QSizePolicy.Expanding) )

        self.setDefaultValues()
        self.apply_operator_settings_to_gui()

        self.editor.showCropLines(True)
        self.editor.cropModel.setEditable (True)
        self.editor.cropModel.changed.connect(self.onCropModelChanged)
        self.editor.posModel.timeChanged.connect(self.updateTime)
        self._cropControlUi._minSliderT.valueChanged.connect(self._onMinSliderTMoved)
        self._cropControlUi._maxSliderT.valueChanged.connect(self._onMaxSliderTMoved)
        self._cropControlUi._minSliderX.valueChanged.connect(self._onMinSliderXMoved)
        self._cropControlUi._maxSliderX.valueChanged.connect(self._onMaxSliderXMoved)
        self._cropControlUi._minSliderY.valueChanged.connect(self._onMinSliderYMoved)
        self._cropControlUi._maxSliderY.valueChanged.connect(self._onMaxSliderYMoved)
        self._cropControlUi._minSliderZ.valueChanged.connect(self._onMinSliderZMoved)
        self._cropControlUi._maxSliderZ.valueChanged.connect(self._onMaxSliderZMoved)

        self._cropControlUi.cropListView.deleteCrop.connect(self.onDeleteCrop)
        self._cropControlUi.cropListView.colorsChanged.connect(self.onColorsChanged)

        self._initCropListView()
Example #25
0
    def __init__(self, parentApplet, topLevelOperator):
        super(DataExportGui, self).__init__()

        self.drawer = None
        self.topLevelOperator = topLevelOperator

        self.threadRouter = ThreadRouter(self)
        self._thunkEventHandler = ThunkEventHandler(self)

        self._initAppletDrawerUic()
        self.initCentralUic()
        self.initViewerControls()

        self.parentApplet = parentApplet
        self.progressSignal = parentApplet.progressSignal

        self.overwrite = False

        @threadRoutedWithRouter(self.threadRouter)
        def handleNewDataset(multislot, index):
            # Make room in the GUI table
            self.batchOutputTableWidget.insertRow(index)

            # Update the table row data when this slot has new data
            # We can't bind in the row here because the row may change in the meantime.
            multislot[index].notifyReady(bind(self.updateTableForSlot))
            if multislot[index].ready():
                self.updateTableForSlot(multislot[index])

            multislot[index].notifyUnready(self._updateExportButtons)
            multislot[index].notifyReady(self._updateExportButtons)

        self.topLevelOperator.ExportPath.notifyInserted(bind(handleNewDataset))

        # For each dataset that already exists, update the GUI
        for i, subslot in enumerate(self.topLevelOperator.ExportPath):
            handleNewDataset(self.topLevelOperator.ExportPath, i)
            if subslot.ready():
                self.updateTableForSlot(subslot)

        @threadRoutedWithRouter(self.threadRouter)
        def handleLaneRemoved(multislot, index, finalLength):
            if self.batchOutputTableWidget.rowCount() <= finalLength:
                return

            # Remove the row we don't need any more
            self.batchOutputTableWidget.removeRow(index)

            # Remove the viewer for this dataset
            imageMultiSlot = self.topLevelOperator.Inputs[index]
            if imageMultiSlot in self.layerViewerGuis.keys():
                layerViewerGui = self.layerViewerGuis[imageMultiSlot]
                self.viewerStack.removeWidget(layerViewerGui)
                self._viewerControlWidgetStack.removeWidget(
                    layerViewerGui.viewerControlWidget())
                layerViewerGui.stopAndCleanUp()

        self.topLevelOperator.Inputs.notifyRemove(bind(handleLaneRemoved))
Example #26
0
    def __init__(self, topLevelOperatorView, additionalMonitoredSlots=[], centralWidgetOnly=False, crosshair=True):
        """
        Constructor.  **All** slots of the provided *topLevelOperatorView* will be monitored for changes.
        Changes include slot resize events, and slot ready/unready status changes.
        When a change is detected, the `setupLayers()` function is called, and the result is used to update the list of layers shown in the central widget.

        :param topLevelOperatorView: The top-level operator for the applet this GUI belongs to.
        :param additionalMonitoredSlots: Optional.  Can be used to add additional slots to the set of viewable layers (all slots from the top-level operator are already monitored).
        :param centralWidgetOnly: If True, provide only a central widget without drawer or viewer controls.
        """
        super(LayerViewerGui, self).__init__()

        self._stopped = False
        self._initialized = False

        self.threadRouter = ThreadRouter(self) # For using @threadRouted

        self.topLevelOperatorView = topLevelOperatorView

        observedSlots = []

        for slot in topLevelOperatorView.inputs.values() + topLevelOperatorView.outputs.values():
            if slot.level == 0 or slot.level == 1:
                observedSlots.append(slot)
        
        observedSlots += additionalMonitoredSlots

        self._orphanOperators = [] # Operators that are owned by this GUI directly (not owned by the top-level operator)
        self.observedSlots = []
        for slot in observedSlots:
            if slot.level == 0:
                if not isinstance(slot.stype, ArrayLike):
                    # We don't support visualization of non-Array slots.
                    continue
                # To be monitored and updated correctly by this GUI, slots must have level=1, but this slot is of level 0.
                # Pass it through a trivial "up-leveling" operator so it will have level 1 for our purposes.
                opPromoteInput = Op1ToMulti(graph=slot.operator.graph)
                opPromoteInput.Input.connect(slot)
                slot = opPromoteInput.Outputs
                self._orphanOperators.append( opPromoteInput )

            # Each slot should now be indexed as slot[layer_index]
            assert slot.level == 1
            self.observedSlots.append( slot )
            slot.notifyInserted( bind(self._handleLayerInsertion) )
            slot.notifyRemoved( bind(self._handleLayerRemoval) )
            for i in range(len(slot)):
                self._handleLayerInsertion(slot, i)
 
        self.layerstack = LayerStackModel()

        self._initCentralUic()
        self._initEditor(crosshair=crosshair)
        self.__viewerControlWidget = None
        if not centralWidgetOnly:
            self.initViewerControlUi() # Might be overridden in a subclass. Default implementation loads a standard layer widget.
            #self._drawer = QWidget( self )
            self.initAppletDrawerUi() # Default implementation loads a blank drawer from drawer.ui.
Example #27
0
    def __init__(self, parentApplet, topLevelOperator):
        super(DataExportGui, self).__init__()

        self.drawer = None
        self.topLevelOperator = topLevelOperator

        self.threadRouter = ThreadRouter(self)
        self._thunkEventHandler = ThunkEventHandler(self)
        
        self._initAppletDrawerUic()
        self.initCentralUic()
        self.initViewerControls()
        
        self.parentApplet = parentApplet
        self.progressSignal = parentApplet.progressSignal

        self.overwrite = False
        
        @threadRoutedWithRouter(self.threadRouter)
        def handleNewDataset( multislot, index ):
            # Make room in the GUI table
            self.batchOutputTableWidget.insertRow( index )
            
            # Update the table row data when this slot has new data
            # We can't bind in the row here because the row may change in the meantime.
            multislot[index].notifyReady( bind( self.updateTableForSlot ) )
            if multislot[index].ready():
                self.updateTableForSlot( multislot[index] )

            multislot[index].notifyUnready( self._updateExportButtons )
            multislot[index].notifyReady( self._updateExportButtons )

        self.topLevelOperator.ExportPath.notifyInserted( bind( handleNewDataset ) )
        
        # For each dataset that already exists, update the GUI
        for i, subslot in enumerate(self.topLevelOperator.ExportPath):
            handleNewDataset( self.topLevelOperator.ExportPath, i )
            if subslot.ready():
                self.updateTableForSlot(subslot)

        @threadRoutedWithRouter(self.threadRouter)
        def handleLaneRemoved( multislot, index, finalLength ):
            if self.batchOutputTableWidget.rowCount() <= finalLength:
                return

            # Remove the row we don't need any more
            self.batchOutputTableWidget.removeRow( index )

            # Remove the viewer for this dataset
            imageMultiSlot = self.topLevelOperator.Inputs[index]
            if imageMultiSlot in list(self.layerViewerGuis.keys()):
                layerViewerGui = self.layerViewerGuis[imageMultiSlot]
                self.viewerStack.removeWidget( layerViewerGui )
                self._viewerControlWidgetStack.removeWidget( layerViewerGui.viewerControlWidget() )
                layerViewerGui.stopAndCleanUp()

        self.topLevelOperator.Inputs.notifyRemove( bind( handleLaneRemoved ) )
Example #28
0
    def __init__(self, parentApplet, topLevelOperatorView, labelingDrawerUiPath=None):
        labelSlots = LabelingGui.LabelingSlots()
        labelSlots.labelInput = topLevelOperatorView.LabelInputs
        labelSlots.labelOutput = topLevelOperatorView.LabelImages
        labelSlots.labelEraserValue = topLevelOperatorView.opLabelPipeline.opLabelArray.eraser
        labelSlots.labelDelete = topLevelOperatorView.opLabelPipeline.DeleteLabel
        labelSlots.labelNames = topLevelOperatorView.LabelNames
        self.parentApplet = parentApplet

        if labelingDrawerUiPath is None:
            localDir = os.path.split(__file__)[0]
            labelingDrawerUiPath = os.path.join(localDir, "nnClass.ui")

        super(NNClassGui, self).__init__(parentApplet, labelSlots, topLevelOperatorView, labelingDrawerUiPath)

        self._initCheckpointActions()

        self.classifiers = OrderedDict()

        self.liveTraining = False
        self.livePrediction = False

        self.__cleanup_fns = []

        self.labelingDrawerUi.liveTraining.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.labelingDrawerUi.liveTraining.toggled.connect(self.toggleLiveTraining)

        self.labelingDrawerUi.livePrediction.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.set_live_predict_icon(self.livePrediction)
        self.labelingDrawerUi.livePrediction.toggled.connect(self.toggleLivePrediction)

        self.labelingDrawerUi.addModel.clicked.connect(self.addModelClicked)
        self.labelingDrawerUi.closeModel.setIcon(QIcon(ilastikIcons.ProcessStop))
        self.labelingDrawerUi.closeModel.clicked.connect(self.closeModelClicked)
        self.labelingDrawerUi.uploadModel.setIcon(QIcon(ilastikIcons.Upload))
        self.labelingDrawerUi.uploadModel.clicked.connect(self.uploadModelClicked)

        self.initViewerControls()
        self.initViewerControlUi()

        self.labelingDrawerUi.labelListView.support_merges = True
        self.batch_size = self.topLevelOperatorView.Batch_Size.value
        self.labelingDrawerUi.labelListView.allowDelete = False
        self.labelingDrawerUi.AddLabelButton.setEnabled(False)
        self.labelingDrawerUi.AddLabelButton.hide()

        self.topLevelOperatorView.LabelNames.notifyDirty(bind(self.handleLabelSelectionChange))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.LabelNames.unregisterDirty, bind(self.handleLabelSelectionChange))
        )
        self.__cleanup_fns.append(self.topLevelOperatorView.cleanUp)

        self.setLabelingUIEnabled(ALLOW_TRAINING)

        self.invalidatePredictionsTimer = QTimer()
        self.invalidatePredictionsTimer.timeout.connect(self.updatePredictions)
        self.tiktorchModel.registerListener(self._onModelStateChanged)
Example #29
0
 def handleLayerInsertion(self, slot, slotIndex):
     """
     The multislot providing our layers has a new item.
     Make room for it in the layer GUI and subscribe to updates.
     """
     with Tracer(traceLogger):
         # When the slot is ready, we'll replace the blank layer with real data
         slot[slotIndex].notifyReady(bind(self.updateAllLayers))
         slot[slotIndex].notifyUnready(bind(self.updateAllLayers))
Example #30
0
    def __init__(self, topLevelOperator, guiControlSignal, progressSignal, title):
        with Tracer(traceLogger):
            super(BatchIoGui, self).__init__()
    
            self.title = title
            self.drawer = None
            self.topLevelOperator = topLevelOperator

            self.threadRouter = ThreadRouter(self)
            
            self.initAppletDrawerUic()
            self.initCentralUic()
            self.chosenExportDirectory = '/'
            self.initViewerControls()
            
            self.guiControlSignal = guiControlSignal
            self.progressSignal = progressSignal
            
            def handleNewDataset( multislot, index ):
                # Make room in the GUI table
                self.batchOutputTableWidget.insertRow( index )
                
                # Update the table row data when this slot has new data
                # We can't bind in the row here because the row may change in the meantime.
                multislot[index].notifyReady( bind( self.updateTableForSlot ) )
                if multislot[index].ready():
                    self.updateTableForSlot( multislot[index] )
    
            self.topLevelOperator.OutputDataPath.notifyInserted( bind( handleNewDataset ) )
            
            # For each dataset that already exists, update the GUI
            for i, subslot in enumerate(self.topLevelOperator.OutputDataPath):
                handleNewDataset( self.topLevelOperator.OutputDataPath, i )
                if subslot.ready():
                    self.updateTableForSlot(subslot)
        
            def handleImageRemoved( multislot, index, finalLength ):
                if self.batchOutputTableWidget.rowCount() <= finalLength:
                    return

                # Remove the row we don't need any more
                self.batchOutputTableWidget.removeRow( index )

                # Remove the viewer for this dataset
                imageSlot = self.topLevelOperator.ImageToExport[index]
                if imageSlot in self.layerViewerGuis.keys():
                    layerViewerGui = self.layerViewerGuis[imageSlot]
                    self.viewerStack.removeWidget( layerViewerGui )
                    self._viewerControlWidgetStack.removeWidget( layerViewerGui.viewerControlWidget() )
                    layerViewerGui.stopAndCleanUp()

            self.topLevelOperator.ImageToExport.notifyRemove( bind( handleImageRemoved ) )
            
            self.topLevelOperator.Suffix.notifyDirty( self.updateDrawerGuiFromOperatorSettings )
            self.topLevelOperator.ExportDirectory.notifyDirty( self.updateDrawerGuiFromOperatorSettings )
            self.topLevelOperator.Format.notifyDirty( self.updateDrawerGuiFromOperatorSettings )
            self.updateDrawerGuiFromOperatorSettings()
 def addApplet(self, index, app):
     # Subscribe to progress updates from this applet,
     # and include the applet index in the signal parameters.
     app.progressSignal.connect( bind(self.handleAppletProgress, index) )
     
     # Also subscribe to this applet's serializer progress updates.
     # (Progress will always come from either the serializer or the applet itself; not both at once.)
     for serializer in app.dataSerializers:
         serializer.progressSignal.connect( bind( self.handleAppletProgress, index ) )
    def __init__(self, topLevelOperator, projectFileGroupName):
        super( FeatureSelectionSerializer, self ).__init__( projectFileGroupName)
        self.topLevelOperator = topLevelOperator    
        self._dirty = False

        def handleDirty():
            self._dirty = True
        self.topLevelOperator.Scales.notifyDirty( bind(handleDirty) )
        self.topLevelOperator.FeatureIds.notifyDirty( bind(handleDirty) )
        self.topLevelOperator.SelectionMatrix.notifyDirty( bind(handleDirty) )
Example #33
0
    def addApplet(self, index, app):
        # Subscribe to progress updates from this applet,
        # and include the applet index in the signal parameters.
        app.progressSignal.connect(bind(self.handleAppletProgress, index))

        # Also subscribe to this applet's serializer progress updates.
        # (Progress will always come from either the serializer or the applet itself; not both at once.)
        for serializer in app.dataSerializers:
            serializer.progressSignal.connect(
                bind(self.handleAppletProgress, index))
Example #34
0
    def _handleLayerInsertion(self, slot, slotIndex):
        """
        The multislot providing our layers has a new item.
        Make room for it in the layer GUI and subscribe to updates.
        """
        # When the slot is ready, we'll replace the blank layer with real data
        slot[slotIndex].notifyReady( bind(self.setNeedUpdate) )
        slot[slotIndex].notifyUnready( bind(self.setNeedUpdate) )

        self.__cleanup_fns.append( partial( slot[slotIndex].unregisterReady, bind(self.setNeedUpdate) ) )
        self.__cleanup_fns.append( partial( slot[slotIndex].unregisterUnready, bind(self.setNeedUpdate) ) )
Example #35
0
    def _handleLayerInsertion(self, slot, slotIndex):
        """
        The multislot providing our layers has a new item.
        Make room for it in the layer GUI and subscribe to updates.
        """
        # When the slot is ready, we'll replace the blank layer with real data
        slot[slotIndex].notifyReady( bind(self.setNeedUpdate) )
        slot[slotIndex].notifyUnready( bind(self.setNeedUpdate) )

        self.__cleanup_fns.append( partial( slot[slotIndex].unregisterReady, bind(self.setNeedUpdate) ) )
        self.__cleanup_fns.append( partial( slot[slotIndex].unregisterUnready, bind(self.setNeedUpdate) ) )
Example #36
0
    def __init__(self, parent, topLevelOperator, roleIndex):
        """
        :param topLevelOperator: An instance of OpMultiLaneDataSelectionGroup
        """
        # super does not work here in Python 2.x, decorated class confuses it
        QAbstractItemModel.__init__(self, parent)
        self._op = topLevelOperator
        self._roleIndex = roleIndex

        def handleNewLane(multislot, laneIndex):
            assert multislot is self._op.DatasetGroup
            self.beginInsertRows(QModelIndex(), laneIndex, laneIndex)
            self.endInsertRows()

            def handleDatasetInfoChanged(slot):
                # Get the row of this slot
                laneSlot = slot.operator
                if laneSlot is None or laneSlot.operator is None:  # This can happen during disconnect
                    return
                try:
                    laneIndex = laneSlot.operator.index(laneSlot)
                except ValueError:
                    # If the slot doesn't exist in the lane,
                    #  then this dataset is in the process of being removed.
                    return
                firstIndex = self.createIndex(laneIndex, 0)
                lastIndex = self.createIndex(laneIndex, self.columnCount() - 1)
                self.dataChanged.emit(firstIndex, lastIndex)

            def handleNewDatasetInserted(slot, index):
                if index == self._roleIndex:
                    datasetMultiSlot[self._roleIndex].notifyDirty(
                        bind(handleDatasetInfoChanged))
                    datasetMultiSlot[self._roleIndex].notifyDisconnect(
                        bind(handleDatasetInfoChanged))

            for laneIndex, datasetMultiSlot in enumerate(
                    self._op.DatasetGroup):
                datasetMultiSlot.notifyInserted(bind(handleNewDatasetInserted))
                if self._roleIndex < len(datasetMultiSlot):
                    handleNewDatasetInserted(datasetMultiSlot, self._roleIndex)

        self._op.DatasetGroup.notifyInserted(bind(handleNewLane))

        def handleLaneRemoved(multislot, laneIndex):
            assert multislot is self._op.DatasetGroup
            self.beginRemoveRows(QModelIndex(), laneIndex, laneIndex)
            self.endRemoveRows()

        self._op.DatasetGroup.notifyRemoved(bind(handleLaneRemoved))

        # Any lanes that already exist must be added now.
        for laneIndex, slot in enumerate(self._op.DatasetGroup):
            handleNewLane(self._op.DatasetGroup, laneIndex)
Example #37
0
    def initAppletDrawerUi(self):
        """
        Reimplemented from LayerViewerGui base class.
        """
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir + "/drawer.ui")

        self._drawer.applyButton.clicked.connect(self._onApplyButtonClicked)
        self._drawer.tabWidget.currentChanged.connect(
            self._onTabCurrentChanged)

        self._sigmaSpinBoxes = {
            'x': self._drawer.sigmaSpinBox_X,
            'y': self._drawer.sigmaSpinBox_Y,
            'z': self._drawer.sigmaSpinBox_Z
        }

        self._allWatchedWidgets = self._sigmaSpinBoxes.values() + \
        [
            self._drawer.inputChannelSpinBox,
            self._drawer.lowThresholdSpinBox,
            self._drawer.highThresholdSpinBox,
            self._drawer.thresholdSpinBox,
            self._drawer.minSizeSpinBox,
            self._drawer.maxSizeSpinBox
        ]

        for widget in self._allWatchedWidgets:
            # If the user pressed enter inside a spinbox, auto-click "Apply"
            widget.installEventFilter(self)

        self._drawer.showDebugCheckbox.stateChanged.connect(
            self._onShowDebugChanged)
        self._showDebug = False

        self._updateGuiFromOperator()
        self.topLevelOperatorView.InputImage.notifyReady(
            bind(self._updateGuiFromOperator))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.InputImage.unregisterUnready,
                    bind(self._updateGuiFromOperator)))

        self.topLevelOperatorView.InputImage.notifyMetaChanged(
            bind(self._updateGuiFromOperator))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.InputImage.unregisterMetaChanged,
                    bind(self._updateGuiFromOperator)))

        # check if the data is 2D. If so, hide the z-sigma
        if self.topLevelOperatorView.InputImage.ready():
            tShape = self.topLevelOperatorView.InputImage.meta.getTaggedShape()
            if not 'z' in tShape or tShape['z'] == 1:
                self._drawer.sigmaSpinBox_Z.setVisible(False)
    def __init__(self, topLevelOperator, projectFileGroupName):
        super( FeatureSelectionSerializer, self ).__init__( projectFileGroupName)
        self.topLevelOperator = topLevelOperator    
        self._dirty = False

        def handleDirty():
            if not self.ignoreDirty:
                self._dirty = True

        self.topLevelOperator.Scales.notifyDirty( bind(handleDirty) )
        self.topLevelOperator.FeatureIds.notifyDirty( bind(handleDirty) )
        self.topLevelOperator.SelectionMatrix.notifyDirty( bind(handleDirty) )
Example #39
0
    def __init__(self, mainOperator, projectFileGroupName):
        super(FeatureSelectionSerializer,
              self).__init__(projectFileGroupName, self.SerializerVersion)
        self.mainOperator = mainOperator
        self._dirty = False

        def handleDirty():
            self._dirty = True

        self.mainOperator.Scales.notifyDirty(bind(handleDirty))
        self.mainOperator.FeatureIds.notifyDirty(bind(handleDirty))
        self.mainOperator.SelectionMatrix.notifyDirty(bind(handleDirty))
Example #40
0
    def __init__(self, dataSelectionOperator, serializer, guiControlSignal, guiMode=GuiMode.Normal, title="Input Selection"):
        with Tracer(traceLogger):
            super(DataSelectionGui, self).__init__()

            self.title = title

            self.drawer = None
            self.topLevelOperator = dataSelectionOperator
            self.guiMode = guiMode
            self.serializer = serializer
            self.guiControlSignal = guiControlSignal
            self.threadRouter = ThreadRouter(self)

            self.initAppletDrawerUic()
            self.initCentralUic()

            def handleNewDataset( multislot, index, finalSize):
                # Subtlety here: This if statement is needed due to the fact that
                #  This code is hit twice on startup: Once in response to a ImageName resize
                #  (during construction) and once for Dataset resize.
                if self.fileInfoTableWidget.rowCount() < finalSize:
                    assert multislot == self.topLevelOperator.Dataset
                    # Make room in the table
                    self.fileInfoTableWidget.insertRow( index )

                    # Update the table row data when this slot has new data
                    # We can't bind in the row here because the row may change in the meantime.
                    self.topLevelOperator.Dataset[index].notifyDirty( self.updateTableForSlot )

            self.topLevelOperator.Dataset.notifyInserted( bind( handleNewDataset ) )

            # For each dataset that already exists, update the GUI
            for i, subslot in enumerate(self.topLevelOperator.Dataset):
                handleNewDataset( self.topLevelOperator.Dataset, i, len(self.topLevelOperator.Dataset) )
                if subslot.ready():
                    self.updateTableForSlot(subslot)

            def handleDatasetRemoved( multislot, index, finalLength ):
                assert multislot == self.topLevelOperator.Dataset
                if self.fileInfoTableWidget.rowCount() > finalLength:
                    # Remove the row we don't need any more
                    self.fileInfoTableWidget.removeRow( index )

            def handleImageRemoved(multislot, index, finalLength):
                # Remove the viewer for this dataset
                imageSlot = self.topLevelOperator.Image[index]
                if imageSlot in self.volumeEditors.keys():
                    editor = self.volumeEditors[imageSlot]
                    self.viewerStack.removeWidget( editor )
                    editor.stopAndCleanUp()

            self.topLevelOperator.Dataset.notifyRemove( bind( handleDatasetRemoved ) )
            self.topLevelOperator.Image.notifyRemove( bind( handleImageRemoved ) )
Example #41
0
    def __init__(self, topLevelOperatorView, applet):
        """
        """
        self.topLevelOperatorView = topLevelOperatorView
        super(FeatureSelectionGui, self).__init__(topLevelOperatorView, crosshair=False)
        self.applet = applet
        self.topLevelOperatorView.SelectionMatrix.notifyDirty( bind(self.onFeaturesSelectionsChanged) )
        self.topLevelOperatorView.FeatureListFilename.notifyDirty( bind(self.onFeaturesSelectionsChanged) )
        self.onFeaturesSelectionsChanged()

        # Init feature dialog
        self.initFeatureDlg()
Example #42
0
    def initAppletDrawerUi(self):
        """
        Reimplemented from LayerViewerGui base class.
        """
        # Load the ui file (find it in our own directory)
        localDir = os.path.split(__file__)[0]
        self._drawer = uic.loadUi(localDir + "/drawer.ui")

        self._drawer.methodComboBox.addItem("Simple")
        self._drawer.methodComboBox.addItem("Hysteresis")
        if _has_graphcut:
            self._drawer.methodComboBox.addItem("Graph Cut")

        self._sigmaSpinBoxes = {
            'x': self._drawer.sigmaSpinBox_X,
            'y': self._drawer.sigmaSpinBox_Y,
            'z': self._drawer.sigmaSpinBox_Z
        }

        self._allWatchedWidgets = list(self._sigmaSpinBoxes.values()) + \
        [
            self._drawer.inputChannelComboBox,
            self._drawer.coreChannelComboBox,
            self._drawer.lowThresholdSpinBox,
            self._drawer.highThresholdSpinBox,
            self._drawer.minSizeSpinBox,
            self._drawer.maxSizeSpinBox,
            self._drawer.lambdaSpinBoxGC
        ]

        for widget in self._allWatchedWidgets:
            # If the user pressed enter inside a spinbox, auto-click "Apply"
            widget.installEventFilter(self)

        self._drawer.showDebugCheckbox.stateChanged.connect(
            self._onShowDebugChanged)
        self._showDebug = False

        self._updateGuiFromOperator()
        self.topLevelOperatorView.InputChannelColors.notifyReady(
            bind(self._updateGuiFromOperator))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.InputImage.unregisterUnready,
                    bind(self._updateGuiFromOperator)))

        self.topLevelOperatorView.InputChannelColors.notifyMetaChanged(
            bind(self._updateGuiFromOperator))
        self.__cleanup_fns.append(
            partial(self.topLevelOperatorView.InputImage.unregisterMetaChanged,
                    bind(self._updateGuiFromOperator)))
    def __init__(self, parent, topLevelOperator, roleIndex):
        """
        :param topLevelOperator: An instance of OpMultiLaneDataSelectionGroup
        """
        # super does not work here in Python 2.x, decorated class confuses it
        QAbstractItemModel.__init__(self, parent)
        self._op = topLevelOperator
        self._roleIndex = roleIndex

        def handleNewLane( multislot, laneIndex):
            assert multislot is self._op.DatasetGroup
            self.beginInsertRows( QModelIndex(), laneIndex, laneIndex )
            self.endInsertRows()

            def handleDatasetInfoChanged(slot):
                # Get the row of this slot
                laneSlot = slot.operator
                if laneSlot is None or laneSlot.operator is None: # This can happen during disconnect
                    return
                try:
                    laneIndex = laneSlot.operator.index( laneSlot )
                except ValueError:
                    # If the slot doesn't exist in the lane, 
                    #  then this dataset is in the process of being removed.
                    return
                firstIndex = self.createIndex(laneIndex, 0)
                lastIndex = self.createIndex(laneIndex, self.columnCount()-1)
                self.dataChanged.emit(firstIndex, lastIndex)
            
            def handleNewDatasetInserted(slot, index):
                if index == self._roleIndex:
                    datasetMultiSlot[self._roleIndex].notifyDirty( bind(handleDatasetInfoChanged) )
                    datasetMultiSlot[self._roleIndex].notifyDisconnect( bind(handleDatasetInfoChanged) )

            for laneIndex, datasetMultiSlot in enumerate( self._op.DatasetGroup ):
                datasetMultiSlot.notifyInserted( bind(handleNewDatasetInserted) )
                if self._roleIndex < len(datasetMultiSlot):
                    handleNewDatasetInserted(datasetMultiSlot, self._roleIndex)

        self._op.DatasetGroup.notifyInserted( bind(handleNewLane) )

        def handleLaneRemoved( multislot, laneIndex ):
            assert multislot is self._op.DatasetGroup
            self.beginRemoveRows( QModelIndex(), laneIndex, laneIndex )
            self.endRemoveRows()
        self._op.DatasetGroup.notifyRemoved( bind(handleLaneRemoved) )

        # Any lanes that already exist must be added now.        
        for laneIndex, slot in enumerate(self._op.DatasetGroup):
            handleNewLane( self._op.DatasetGroup, laneIndex )
Example #44
0
    def __init__(self, parentApplet, croppingSlots, topLevelOperatorView, drawerUiPath=None, rawInputSlot=None, crosshair=True):
        """
        Constructor.

        :param croppingSlots: Provides the slots needed for sourcing/sinking crop data.  See CroppingGui.CroppingSlots
                              class source for details.
        :param topLevelOperatorView: is provided to the LayerViewerGui (the base class)
        :param drawerUiPath: can be given if you provide an extended drawer UI file.  Otherwise a default one is used.
        :param rawInputSlot: Data from the rawInputSlot parameter will be displayed directly underneath the elements
                             (if provided).
        """

        # Do we have all the slots we need?
        assert isinstance(croppingSlots, CroppingGui.CroppingSlots)
        assert croppingSlots.cropInput is not None, "Missing a required slot."
        assert croppingSlots.cropOutput is not None, "Missing a required slot."
        assert croppingSlots.cropEraserValue is not None, "Missing a required slot."
        assert croppingSlots.cropDelete is not None, "Missing a required slot."
        assert croppingSlots.cropNames is not None, "Missing a required slot."
        assert croppingSlots.cropsAllowed is not None, "Missing a required slot."

        self.__cleanup_fns = []
        self._croppingSlots = croppingSlots
        self._minCropNumber = 0
        self._maxCropNumber = 99 #100 or 255 is reserved for eraser

        self._rawInputSlot = rawInputSlot

        self.topLevelOperatorView.Crops.notifyDirty( bind(self._updateCropList) )
        self.topLevelOperatorView.Crops.notifyDirty( bind(self._updateCropList) )
        self.__cleanup_fns.append( partial( self.topLevelOperatorView.Crops.unregisterDirty, bind(self._updateCropList) ) )
        
        self._colorTable16 = colortables.default16_new
        self._programmaticallyRemovingCrops = False

        self._initCropUic(drawerUiPath)

        self._maxCropNumUsed = 0

        self._allowDeleteLastCropOnly = False
        self.__initShortcuts()
        # Init base class
        super(CroppingGui, self).__init__(parentApplet,
                                          topLevelOperatorView,
                                          [croppingSlots.cropInput, croppingSlots.cropOutput],
                                          crosshair=crosshair)
        self._croppingSlots.cropEraserValue.setValue(self.editor.brushingModel.erasingNumber)

        # Register for thunk events (easy UI calls from non-GUI threads)
        self.thunkEventHandler = ThunkEventHandler(self)
Example #45
0
    def __init__(self, labelingSlots, topLevelOperatorView, drawerUiPath=None, rawInputSlot=None, crosshair=True):
        """
        Constructor.

        :param labelingSlots: Provides the slots needed for sourcing/sinking label data.  See LabelingGui.LabelingSlots
                              class source for details.
        :param topLevelOperatorView: is provided to the LayerViewerGui (the base class)
        :param drawerUiPath: can be given if you provide an extended drawer UI file.  Otherwise a default one is used.
        :param rawInputSlot: Data from the rawInputSlot parameter will be displayed directly underneath the elements
                             (if provided).
        """

        # Do have have all the slots we need?
        assert isinstance(labelingSlots, LabelingGui.LabelingSlots)
        assert all( [v is not None for v in labelingSlots.__dict__.values()] )

        self.__cleanup_fns = []

        self._labelingSlots = labelingSlots
        self._minLabelNumber = 0
        self._maxLabelNumber = 99 #100 or 255 is reserved for eraser

        self._rawInputSlot = rawInputSlot

        self._labelingSlots.maxLabelValue.notifyDirty( bind(self._updateLabelList) )
        self.__cleanup_fns.append( partial( self._labelingSlots.maxLabelValue.unregisterDirty, bind(self._updateLabelList) ) )

        if self._labelingSlots.LabelNames is not None:
            self._labelingSlots.LabelNames.notifyDirty( bind(self._updateLabelList) )
            self.__cleanup_fns.append( partial( self._labelingSlots.LabelNames.unregisterDirty, bind(self._updateLabelList) ) )
        
        self._colorTable16 = self._createDefault16ColorColorTable()
        self._programmaticallyRemovingLabels = False

        if drawerUiPath is None:
            # Default ui file
            drawerUiPath = os.path.split(__file__)[0] + '/labelingDrawer.ui'
        self._initLabelUic(drawerUiPath)

        # Init base class
        super(LabelingGui, self).__init__(topLevelOperatorView,
                                          [labelingSlots.labelInput, labelingSlots.labelOutput],
                                          crosshair=crosshair)

        self.__initShortcuts()
        self._labelingSlots.labelEraserValue.setValue(self.editor.brushingModel.erasingNumber)

        # Register for thunk events (easy UI calls from non-GUI threads)
        self.thunkEventHandler = ThunkEventHandler(self)
        self._changeInteractionMode(Tool.Navigation)
    def __init__(self, parent, topLevelOperator, roleIndex):
        """
        :param topLevelOperator: An instance of OpMultiLaneDataSelectionGroup
        """
        super(DatasetDetailedInfoTableModel, self).__init__(parent)
        self._op = topLevelOperator
        self._roleIndex = roleIndex

        def handleNewLane(multislot, laneIndex):
            assert multislot is self._op.DatasetGroup
            self.beginInsertRows(QModelIndex(), laneIndex, laneIndex)
            self.endInsertRows()

            def handleDatasetInfoChanged(slot):
                # Get the row of this slot
                laneSlot = slot.operator
                if laneSlot is None or laneSlot.operator is None:  # This can happen during disconnect
                    return
                laneIndex = laneSlot.operator.index(laneSlot)
                firstIndex = self.createIndex(laneIndex, 0)
                lastIndex = self.createIndex(laneIndex, self.columnCount() - 1)
                self.dataChanged.emit(firstIndex, lastIndex)

            def handleNewDatasetInserted(slot, index):
                if index == self._roleIndex:
                    datasetMultiSlot[self._roleIndex].notifyDirty(
                        bind(handleDatasetInfoChanged))
                    datasetMultiSlot[self._roleIndex].notifyDisconnect(
                        bind(handleDatasetInfoChanged))

            for laneIndex, datasetMultiSlot in enumerate(
                    self._op.DatasetGroup):
                datasetMultiSlot.notifyInserted(bind(handleNewDatasetInserted))
                if self._roleIndex < len(datasetMultiSlot):
                    handleNewDatasetInserted(datasetMultiSlot, self._roleIndex)

        self._op.DatasetGroup.notifyInserted(bind(handleNewLane))

        def handleLaneRemoved(multislot, laneIndex):
            assert multislot is self._op.DatasetGroup
            self.beginRemoveRows(QModelIndex(), laneIndex, laneIndex)
            self.endRemoveRows()

        self._op.DatasetGroup.notifyRemoved(bind(handleLaneRemoved))

        # Any lanes that already exist must be added now.
        for laneIndex, slot in enumerate(self._op.DatasetGroup):
            handleNewLane(self._op.DatasetGroup, laneIndex)
Example #47
0
    def updateTableForSlot(self, slot):
        """
        Update the table row that corresponds to the given slot of the top-level operator (could be either input slot)
        """
        row = self.getSlotIndex( self.topLevelOperator.ExportPath, slot )
        assert row != -1, "Unknown input slot!"

        if not self.topLevelOperator.ExportPath[row].ready() or\
           not self.topLevelOperator.RawDatasetInfo[row].ready():
            return
        
        try:
            nickname = self.topLevelOperator.RawDatasetInfo[row].value.nickname
            exportPath = self.topLevelOperator.ExportPath[row].value
        except Slot.SlotNotReadyError:
            # Sadly, it is possible to get here even though we checked for .ready() immediately beforehand.
            # That's because the graph has a diamond-shaped DAG of connections, but the graph has no transaction mechanism
            # (It's therefore possible for RawDatasetInfo[row] to be ready() even though it's upstream partner is NOT ready.
            return
                
        self.batchOutputTableWidget.setItem( row, Column.Dataset, QTableWidgetItem(nickname) )
        self.batchOutputTableWidget.setItem( row, Column.ExportLocation, QTableWidgetItem( exportPath ) )

        exportNowButton = QPushButton("Export")
        exportNowButton.setToolTip("Generate individual batch output dataset.")
        exportNowButton.clicked.connect( bind(self.exportResultsForSlot, self.topLevelOperator[row] ) )
        self.batchOutputTableWidget.setCellWidget( row, Column.Action, exportNowButton )

        # Select a row if there isn't one already selected.
        selectedRanges = self.batchOutputTableWidget.selectedRanges()
        if len(selectedRanges) == 0:
            self.batchOutputTableWidget.selectRow(0)
        def handleNewLane(multislot, laneIndex):
            assert multislot is self._op.DatasetGroup
            self.beginInsertRows(QModelIndex(), laneIndex, laneIndex)
            self.endInsertRows()

            def handleDatasetInfoChanged(slot):
                # Get the row of this slot
                laneSlot = slot.operator
                if laneSlot is None or laneSlot.operator is None:  # This can happen during disconnect
                    return
                laneIndex = laneSlot.operator.index(laneSlot)
                firstIndex = self.createIndex(laneIndex, 0)
                lastIndex = self.createIndex(laneIndex, self.columnCount() - 1)
                self.dataChanged.emit(firstIndex, lastIndex)

            def handleNewDatasetInserted(slot, index):
                if index == self._roleIndex:
                    datasetMultiSlot[self._roleIndex].notifyDirty(
                        bind(handleDatasetInfoChanged))
                    datasetMultiSlot[self._roleIndex].notifyDisconnect(
                        bind(handleDatasetInfoChanged))

            for laneIndex, datasetMultiSlot in enumerate(
                    self._op.DatasetGroup):
                datasetMultiSlot.notifyInserted(bind(handleNewDatasetInserted))
                if self._roleIndex < len(datasetMultiSlot):
                    handleNewDatasetInserted(datasetMultiSlot, self._roleIndex)
 def __init__(self, mainOperator, projectFileGroupName):
     super( BatchIoSerializer, self ).__init__( projectFileGroupName, self.SerializerVersion )
     self.mainOperator = mainOperator
     
     self._dirty = False
     
     def handleDirty():
         self._dirty = True
     self.mainOperator.ExportDirectory.notifyDirty( bind(handleDirty) )
     self.mainOperator.Format.notifyDirty( bind(handleDirty) )
     self.mainOperator.Suffix.notifyDirty( bind(handleDirty) )
     
     def handleNewDataset(slot, index):
         slot[index].notifyDirty( bind(handleDirty) )
     # DatasetPath is a multi-slot, so subscribe to dirty callbacks on each slot as it is added
     self.mainOperator.DatasetPath.notifyInserted( bind(handleNewDataset) )
    def updateTableForSlot(self, slot):
        """
        Update the table row that corresponds to the given slot of the top-level operator (could be either input slot)
        """
        row = self.getSlotIndex( self.topLevelOperator.ExportPath, slot )
        assert row != -1, "Unknown input slot!"

        if not self.topLevelOperator.ExportPath[row].ready() or\
           not self.topLevelOperator.RawDatasetInfo[row].ready():
            return
        
        try:
            nickname = self.topLevelOperator.RawDatasetInfo[row].value.nickname
            exportPath = self.topLevelOperator.ExportPath[row].value
        except Slot.SlotNotReadyError:
            # Sadly, it is possible to get here even though we checked for .ready() immediately beforehand.
            # That's because the graph has a diamond-shaped DAG of connections, but the graph has no transaction mechanism
            # (It's therefore possible for RawDatasetInfo[row] to be ready() even though it's upstream partner is NOT ready.
            return
                
        self.batchOutputTableWidget.setItem( row, Column.Dataset, QTableWidgetItem( decode_to_qstring(nickname, 'utf-8') ) )
        self.batchOutputTableWidget.setItem( row, Column.ExportLocation, QTableWidgetItem( decode_to_qstring(exportPath) ) )

        exportNowButton = QPushButton("Export")
        exportNowButton.setToolTip("Generate individual batch output dataset.")
        exportNowButton.clicked.connect( bind(self.exportResultsForSlot, self.topLevelOperator[row] ) )
        self.batchOutputTableWidget.setCellWidget( row, Column.Action, exportNowButton )

        # Select a row if there isn't one already selected.
        selectedRanges = self.batchOutputTableWidget.selectedRanges()
        if len(selectedRanges) == 0:
            self.batchOutputTableWidget.selectRow(0)
Example #51
0
 def exportResultsForSlot(self, slot, progressSlot):
     with Tracer(traceLogger):
         # Do this in a separate thread so the UI remains responsive
         exportThread = threading.Thread(target=bind(
             self.exportSlots, [slot], [progressSlot]),
                                         name="BatchIOExportThread")
         exportThread.start()
Example #52
0
            def handleNewDataset(multislot, index):
                # Make room in the GUI table
                self.tableWidget.insertRow(index)

                # Update the table row data when this slot has new data
                # We can't bind in the row here because the row may change in the meantime.
                multislot[index].notifyDirty(bind(self.updateTableForSlot))
    def _ensurePipelineExists(self, block_start):
        if block_start in self._blockPipelines:
            return
        with self._lock:
            if block_start in self._blockPipelines:
                return

            logger.debug("Creating pipeline for block: {}".format(block_start))

            block_shape = self._getFullShape(self._block_shape_dict)
            halo_padding = self._getFullShape(self._halo_padding_dict)

            input_shape = self.RawImage.meta.shape
            block_stop = getBlockBounds(input_shape, block_shape,
                                        block_start)[1]
            block_roi = (block_start, block_stop)

            # Instantiate pipeline
            opBlockPipeline = OpSingleBlockObjectPrediction(block_roi,
                                                            halo_padding,
                                                            parent=self)
            opBlockPipeline.RawImage.connect(self.RawImage)
            opBlockPipeline.BinaryImage.connect(self.BinaryImage)
            opBlockPipeline.Classifier.connect(self.Classifier)
            opBlockPipeline.LabelsCount.connect(self.LabelsCount)
            opBlockPipeline.SelectedFeatures.connect(self.SelectedFeatures)

            # Forward dirtyness
            opBlockPipeline.PredictionImage.notifyDirty(
                bind(self._handleDirtyBlock, block_start))

            self._blockPipelines[block_start] = opBlockPipeline
Example #54
0
 def exportAllResults(self):
     # Do this in a separate thread so the UI remains responsive
     exportThread = threading.Thread(target=bind(
         self.exportSlots, self.topLevelOperator.ExportResult,
         self.topLevelOperator.ProgressSignal),
                                     name="BatchIOExportThread")
     exportThread.start()
    def __init__(self, topLevelOperatorView, shellRequestSignal,
                 predictionSerializer):
        # Tell our base class which slots to monitor
        labelSlots = LabelingGui.LabelingSlots()
        labelSlots.labelInput = topLevelOperatorView.LabelInputs
        labelSlots.labelOutput = topLevelOperatorView.LabelImages
        labelSlots.labelEraserValue = topLevelOperatorView.opLabelArray.eraser
        labelSlots.labelDelete = topLevelOperatorView.opLabelArray.deleteLabel
        labelSlots.maxLabelValue = topLevelOperatorView.MaxLabelValue

        # We provide our own UI file (which adds an extra control for interactive mode)
        labelingDrawerUiPath = os.path.split(
            __file__)[0] + '/labelingDrawer.ui'

        # Base class init
        super(AutocontextClassificationGui,
              self).__init__(labelSlots, topLevelOperatorView,
                             labelingDrawerUiPath)

        self.topLevelOperatorView = topLevelOperatorView
        self.shellRequestSignal = shellRequestSignal
        self.predictionSerializer = predictionSerializer

        self.interactiveModeActive = False
        self._currentlySavingPredictions = False

        self.labelingDrawerUi.savePredictionsButton.clicked.connect(
            self.onSavePredictionsButtonClicked)
        self.labelingDrawerUi.savePredictionsButton.setIcon(
            QIcon(ilastikIcons.Save))

        self.topLevelOperatorView.MaxLabelValue.notifyDirty(
            bind(self.handleLabelSelectionChange))
Example #56
0
    def updateInternalPathComboBox( self, row, externalPath, internalPath ):
        with Tracer(traceLogger):
            combo = QComboBox()
            datasetNames = []
    
            # Make sure we're dealing with the absolute path (to make this simple)
            absPath, relPath = getPathVariants(externalPath, self.mainOperator.WorkingDirectory.value)
            ext = os.path.splitext(absPath)[1]
            h5Exts = ['.ilp', '.h5', '.hdf5']
            if ext in h5Exts:
                datasetNames = self.getPossibleInternalPaths(absPath)

            # Add each dataset option to the combo            
            for path in datasetNames:
                combo.addItem( path )
    
            # If the internal path we used previously is in the combo list, select it.
            prevSelection = combo.findText( internalPath )
            if prevSelection != -1:
                combo.setCurrentIndex( prevSelection )
    
            # Define response to changes and add it to the GUI.
            # Pass in the corresponding the table item so we can figure out which row this came from
            combo.currentIndexChanged.connect( bind(self.handleComboSelectionChanged, combo) )
            self.fileInfoTableWidget.setCellWidget( row, Column.InternalID, combo )
    def _ensurePipelineExists(self, block_start):
        if block_start in self._blockPipelines:
            return
        with self._lock:
            if block_start in self._blockPipelines:
                return

            logger.debug( "Creating pipeline for block: {}".format( block_start ) )

            block_shape = self._getFullShape( self._block_shape_dict )
            halo_padding = self._getFullShape( self._halo_padding_dict )

            input_shape = self.RawImage.meta.shape
            block_stop = getBlockBounds( input_shape, block_shape, block_start )[1]
            block_roi = (block_start, block_stop)

            # Instantiate pipeline
            opBlockPipeline = OpSingleBlockObjectPrediction( block_roi, halo_padding, parent=self )
            opBlockPipeline.RawImage.connect( self.RawImage )
            opBlockPipeline.BinaryImage.connect( self.BinaryImage )
            opBlockPipeline.Classifier.connect( self.Classifier )
            opBlockPipeline.LabelsCount.connect( self.LabelsCount )

            # Forward dirtyness
            opBlockPipeline.PredictionImage.notifyDirty( bind(self._handleDirtyBlock, block_start ) )
            
            self._blockPipelines[block_start] = opBlockPipeline
Example #58
0
    def __init__(self, dataSelectionOperator, serializer, guiControlSignal, guiMode=GuiMode.Normal, title="Input Selection"):
        with Tracer(traceLogger):
            super(DataSelectionGui, self).__init__()

            self.title = title

            self._viewerControls = QWidget()
            self.topLevelOperator = dataSelectionOperator
            self.guiMode = guiMode
            self.serializer = serializer
            self.guiControlSignal = guiControlSignal
            self.threadRouter = ThreadRouter(self)

            self._initCentralUic()
            self._initAppletDrawerUic()
            
            self._viewerControlWidgetStack = QStackedWidget(self)

            def handleImageRemoved(multislot, index, finalLength):
                # Remove the viewer for this dataset
                imageSlot = self.topLevelOperator.Image[index]
                if imageSlot in self.volumeEditors.keys():
                    editor = self.volumeEditors[imageSlot]
                    self.viewerStack.removeWidget( editor )
                    self._viewerControlWidgetStack.removeWidget( editor.viewerControlWidget() )
                    editor.stopAndCleanUp()

            self.topLevelOperator.Image.notifyRemove( bind( handleImageRemoved ) )