Esempio n. 1
0
 def expandByShape(self,shape,cIndex,tIndex):
     """
     extend a roi by a given in shape
     """
     #TODO: Warn if bounds are exceeded
     cStart = self.start[cIndex]
     cStop = self.stop[cIndex]
     if tIndex is not None:
         tStart = self.start[tIndex]
         tStop = self.stop[tIndex]
     if isinstance(shape, collections.Iterable):
         #add a dummy number for the channel dimension
         shape = shape+(1,)
     else:
         tmp = shape
         shape = numpy.zeros(self.dim).astype(int)
         shape[:] = tmp
     
     tmpStart = [int(x-s) for x,s in zip(self.start,shape)]
     tmpStop = [int(x+s) for x,s in zip(self.stop,shape)]
     start = [int(max(t,i)) for t,i in zip(tmpStart,numpy.zeros_like(self.inputShape))]   
     stop = [int(min(t,i)) for t,i in zip(tmpStop,self.inputShape)]
     start[cIndex] = cStart
     stop[cIndex] = cStop
     if tIndex is not None:
         start[tIndex] = tStart
         stop[tIndex] = tStop
     self.start = TinyVector(start)
     self.stop = TinyVector(stop)
     return self
Esempio n. 2
0
    def _deserialize(self, mygroup, slot):
        num = len(mygroup)
        if len(self.inslot) < num:
            self.inslot.resize(num)

        # Annoyingly, some applets store their groups with names like, img0,img1,img2,..,img9,img10,img11
        # which means that sorted() needs a special key to avoid sorting img10 before img2
        # We have to find the index and sort according to its numerical value.
        index_capture = re.compile(r"[^0-9]*(\d*).*")

        def extract_index(s):
            return int(index_capture.match(s).groups()[0])

        for index, t in enumerate(
                sorted(list(mygroup.items()),
                       key=lambda k_v1: extract_index(k_v1[0]))):
            groupName, labelGroup = t
            assert extract_index(
                groupName
            ) == index, "subgroup extraction order should be numerical order!"
            for blockRoiString, blockDataset in list(labelGroup.items()):
                blockRoi = convertStringToList(blockRoiString)
                roiShape = TinyVector(blockRoi[1]) - TinyVector(blockRoi[0])
                assert roiShape == blockDataset.shape

                self.inslot[index][roiToSlice(*blockRoi)] = blockDataset
Esempio n. 3
0
    def handleAppletStateUpdateRequested(self):
        """
        Overridden from Workflow base class
        Called when an applet has fired the :py:attr:`Applet.statusUpdateSignal`
        """
        # If no data, nothing else is ready.
        opDataSelection = self.dataSelectionApplet.topLevelOperator
        input_ready = len(opDataSelection.ImageGroup) > 0 and not self.dataSelectionApplet.busy

        opFeatureSelection = self.featureSelectionApplet.topLevelOperator
        featureOutput = opFeatureSelection.OutputImage
        features_ready = input_ready and \
                         len(featureOutput) > 0 and  \
                         featureOutput[0].ready() and \
                         (TinyVector(featureOutput[0].meta.shape) > 0).all()

        opDataExport = self.dataExportApplet.topLevelOperator
        predictions_ready = features_ready and \
                            len(opDataExport.Inputs) > 0 and \
                            opDataExport.Inputs[0][0].ready() and \
                            (TinyVector(opDataExport.Inputs[0][0].meta.shape) > 0).all()

        self._shell.setAppletEnabled(self.featureSelectionApplet, input_ready)
        self._shell.setAppletEnabled(self.countingApplet, features_ready)
        self._shell.setAppletEnabled(self.dataExportApplet, predictions_ready and not self.dataExportApplet.busy)
        self._shell.setAppletEnabled(self.batchProcessingApplet, predictions_ready and not self.batchProcessingApplet.busy)
        
        # Lastly, check for certain "busy" conditions, during which we 
        #  should prevent the shell from closing the project.
        busy = False
        busy |= self.dataSelectionApplet.busy
        busy |= self.featureSelectionApplet.busy
        busy |= self.dataExportApplet.busy
        busy |= self.batchProcessingApplet.busy
        self._shell.enableProjectChanges( not busy )
Esempio n. 4
0
    def expandByShape(self, shape, cIndex, tIndex):
        """
        extend a roi by a given in shape
        """
        # TODO: Warn if bounds are exceeded
        cStart = self.start[cIndex]
        cStop = self.stop[cIndex]
        if tIndex is not None:
            tStart = self.start[tIndex]
            tStop = self.stop[tIndex]
        if type(shape == int):
            tmp = shape
            shape = numpy.zeros(self.dim).astype(int)
            shape[:] = tmp

        tmpStart = [int(x - s) for x, s in zip(self.start, shape)]
        tmpStop = [int(x + s) for x, s in zip(self.stop, shape)]
        start = [int(max(t, i)) for t, i in zip(tmpStart, numpy.zeros_like(self.inputShape))]
        stop = [int(min(t, i)) for t, i in zip(tmpStop, self.inputShape)]
        start[cIndex] = cStart
        stop[cIndex] = cStop
        if tIndex is not None:
            start[tIndex] = tStart
            stop[tIndex] = tStop
        self.start = TinyVector(start)
        self.stop = TinyVector(stop)
        return self
Esempio n. 5
0
    def __init__(self, slot, start = None, stop = None, pslice = None):
        super(SubRegion,self).__init__(slot)
        shape = None
        if slot is not None:
            shape = slot.meta.shape
        if pslice != None or start is not None and stop is None and pslice is None:
            if pslice is None:
                pslice = start
            if shape is None:
                # Okay to use a shapeless slot if the key is bounded
                # AND if the key has the correct length
                assert slicingtools.is_bounded(pslice)
                # Supply a dummy shape
                shape = [0] * len(pslice)
            self.start, self.stop = sliceToRoi(pslice,shape)
        elif start is None and pslice is None:
            assert shape is not None, "Can't create a default subregion without a slot and a shape."
            self.start, self.stop = roiFromShape(shape)
        else:
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        self.dim = len(self.start)

        for start, stop in zip(self.start, self.stop):
            assert isinstance(start, (int, long, numpy.integer)), "Roi contains non-integers: {}".format( self )
            assert isinstance(start, (int, long, numpy.integer)), "Roi contains non-integers: {}".format( self )
Esempio n. 6
0
    def testBasic(self):
        start = TinyVector([10, 100, 200, 300, 1])
        stop = TinyVector([11, 150, 300, 500, 3])
        image_shape = [20, 152, 500, 500, 10]

        sigma = 3.1
        window = 2
        enlarge_axes = (False, True, True, True, False)

        enlarged_start, enlarged_stop = enlargeRoiForHalo(
            start, stop, image_shape, sigma, window, enlarge_axes)

        full_halo_width = numpy.ceil(sigma * window)

        # Non-enlarged axes should remain the same
        assert (enlarged_start[[0, 4]] == (start[0],
                                           start[4])).all(), "{} == {}".format(
                                               enlarged_start[[0, 4]],
                                               (start[0], start[4]))
        assert (enlarged_stop[[0, 4]] == (stop[0],
                                          stop[4])).all(), "{} == {}".format(
                                              enlarged_stop[[0, 4]],
                                              (stop[0], stop[4]))

        # The start coord isn't close to the image border, so the halo should be full-sized on the start side
        assert (enlarged_start[1:4] == numpy.array(start)[1:4] -
                full_halo_width).all()

        # The stop coord is close to the image border in some dimensions,
        #  so some axes couldn't be expanded by the full halo width.
        assert enlarged_stop[1] == 152
        assert enlarged_stop[2] == stop[2] + full_halo_width
        assert enlarged_stop[3] == 500
    def handleAppletStateUpdateRequested(self):
        """
        Overridden from Workflow base class
        Called when an applet has fired the :py:attr:`Applet.appletStateUpdateRequested`
        """
        input_ready = self._inputReady(1)
        cumulated_readyness = input_ready

        cumulated_readyness &= not self.batchProcessingApplet.busy # Nothing can be touched while batch mode is executing.

        opFeatureSelection = self.featureSelectionApplet.topLevelOperator
        featureOutput = opFeatureSelection.OutputImage
        features_ready = len(featureOutput) > 0 and  \
            featureOutput[0].ready() and \
            (TinyVector(featureOutput[0].meta.shape) > 0).all()
        cumulated_readyness = cumulated_readyness and features_ready
        self._shell.setAppletEnabled(self.pcApplet, cumulated_readyness)

        slot = self.pcApplet.topLevelOperator.PredictionProbabilities
        predictions_ready = len(slot) > 0 and \
            slot[0].ready() and \
            (TinyVector(slot[0].meta.shape) > 0).all()

        cumulated_readyness = cumulated_readyness and predictions_ready
        self._shell.setAppletEnabled(self.thresholdingApplet, cumulated_readyness)

        # Problems can occur if the features or input data are changed during live update mode.
        # Don't let the user do that.
        opPixelClassification = self.pcApplet.topLevelOperator
        live_update_active = not opPixelClassification.FreezePredictions.value

        self._shell.setAppletEnabled(self.dataSelectionApplet, not live_update_active)
        self._shell.setAppletEnabled(self.featureSelectionApplet, input_ready and not live_update_active)

        super(ObjectClassificationWorkflowPixel, self).handleAppletStateUpdateRequested(upstream_ready=cumulated_readyness)
    def handleAppletStateUpdateRequested(self):
        """
        Overridden from Workflow base class
        Called when an applet has fired the :py:attr:`Applet.appletStateUpdateRequested`
        """
        # If no data, nothing else is ready.
        opDataSelection = self.dataSelectionApplet.topLevelOperator
        input_ready = len(opDataSelection.ImageGroup
                          ) > 0 and not self.dataSelectionApplet.busy

        opFeatureSelection = self.featureSelectionApplet.topLevelOperator
        featureOutput = opFeatureSelection.OutputImage
        features_ready = input_ready and \
                         len(featureOutput) > 0 and  \
                         featureOutput[0].ready() and \
                         (TinyVector(featureOutput[0].meta.shape) > 0).all()

        opDataExport = self.dataExportApplet.topLevelOperator
        opPixelClassification = self.pcApplet.topLevelOperator

        invalid_classifier = opPixelClassification.classifier_cache.fixAtCurrent.value and \
                             opPixelClassification.classifier_cache.Output.ready() and\
                             opPixelClassification.classifier_cache.Output.value is None

        predictions_ready = features_ready and \
                            not invalid_classifier and \
                            len(opDataExport.Inputs) > 0 and \
                            opDataExport.Inputs[0][0].ready() and \
                            (TinyVector(opDataExport.Inputs[0][0].meta.shape) > 0).all()

        # Problems can occur if the features or input data are changed during live update mode.
        # Don't let the user do that.
        live_update_active = not opPixelClassification.FreezePredictions.value

        self._shell.setAppletEnabled(self.dataSelectionApplet,
                                     not live_update_active)
        self._shell.setAppletEnabled(self.featureSelectionApplet, input_ready
                                     and not live_update_active)
        self._shell.setAppletEnabled(self.pcApplet, features_ready)
        self._shell.setAppletEnabled(self.dataExportApplet, predictions_ready)

        if self.batchInputApplet is not None:
            # Training workflow must be fully configured before batch can be used
            self._shell.setAppletEnabled(self.batchInputApplet,
                                         predictions_ready)

            opBatchDataSelection = self.batchInputApplet.topLevelOperator
            batch_input_ready = predictions_ready and \
                                len(opBatchDataSelection.ImageGroup) > 0
            self._shell.setAppletEnabled(self.batchResultsApplet,
                                         batch_input_ready)

        # Lastly, check for certain "busy" conditions, during which we
        #  should prevent the shell from closing the project.
        busy = False
        busy |= self.dataSelectionApplet.busy
        busy |= self.featureSelectionApplet.busy
        busy |= self.dataExportApplet.busy
        self._shell.enableProjectChanges(not busy)
Esempio n. 9
0
 def __setstate__(self, state):
     """
     Support copy.copy()
     """
     self.slot = state['slot']
     self.start = TinyVector( state['start'] )
     self.stop = TinyVector( state['stop'] )
     self.dim = len( state['start'] )
Esempio n. 10
0
    def test_roiToSlice(self):
        from lazyflow.roi import TinyVector
        shape = (2, 4, 6, 8, 10)

        roi = (TinyVector((1, 2, 3, 4, 5)), TinyVector(shape))
        assert lazyflow.roi.roiToSlice(roi[0],
                                       roi[1]) == (slice(1, 2), slice(2, 4),
                                                   slice(3, 6), slice(4, 8),
                                                   slice(5, 10))
Esempio n. 11
0
    def _impl_roi_custom_order(self, axisorder):
        for i in range(self.tests):
            config_via_init = bool(i % 2)
            # Specify a strange order for the output axis tags
            self.prepareVolnOp(axisorder,
                               len(axisorder) - 1,
                               AxisOrder=axisorder,
                               config_via_init=config_via_init)

            shape = self.operator.Output.meta.shape

            roi = [None, None]
            roi[1] = [
                numpy.random.randint(2, s) if s != 1 else 1 for s in shape
            ]
            roi[0] = [
                numpy.random.randint(0, roi[1][i]) if s != 1 else 0
                for i, s in enumerate(shape)
            ]
            roi[0] = TinyVector(roi[0])
            roi[1] = TinyVector(roi[1])
            result = self.operator.Output(roi[0], roi[1]).wait()
            logger.debug(
                "------------------------------------------------------")
            logger.debug("self.array.shape = " + str(self.array.shape))
            logger.debug("type(input) == " +
                         str(type(self.operator.Input.value)))
            logger.debug("input.shape == " +
                         str(self.operator.Input.meta.shape))
            logger.debug("Input Tags:")
            logger.debug(str(self.operator.Input.meta.axistags))
            logger.debug("Output Tags:")
            logger.debug(str(self.operator.Output.meta.axistags))
            logger.debug("roi= " + str(roi))
            logger.debug("type(result) == " + str(type(result)))
            logger.debug("result.shape == " + str(result.shape))
            logger.debug(
                "------------------------------------------------------")

            # Check the shape
            assert len(result.shape) == len(axisorder)

            assert not isinstance(
                result, vigra.VigraArray
            ), "For compatibility with generic code, output should be provided as a plain numpy array."

            # Ensure the result came out in the same strange order we asked for.
            assert self.operator.Output.meta.axistags == vigra.defaultAxistags(
                axisorder)

            # Check the data
            vresult = result.view(vigra.VigraArray)
            vresult.axistags = self.operator.Output.meta.axistags
            reorderedInput = self.inArray.withAxes(
                *[tag.key for tag in self.operator.Output.meta.axistags])
            assert numpy.all(
                vresult == reorderedInput[roiToSlice(roi[0], roi[1])])
Esempio n. 12
0
 def testAny(self):
     a = TinyVector([True, True, True])
     b = TinyVector([True, False, True])
     c = TinyVector([False, False, False])
     assert a.any()
     assert b.any()
     assert not c.any()
Esempio n. 13
0
    def setUp(self):
        self.v1 = TinyVector(range(1, 11))
        self.v2 = TinyVector(range(11, 21))

        self.a1 = numpy.array(self.v1)
        self.a2 = numpy.array(self.v2)

        self.l1 = list(self.v1)
        self.l2 = list(self.v2)

        self.scalar = 3
Esempio n. 14
0
    def setup_method(self, method):
        self.v1 = TinyVector(list(range(1, 11)))
        self.v2 = TinyVector(list(range(11, 21)))

        self.a1 = numpy.array(self.v1)
        self.a2 = numpy.array(self.v2)

        self.l1 = list(self.v1)
        self.l2 = list(self.v2)

        self.scalar = 3
    def test_insert_singleton_axis(self):
        for i in range(self.tests):
            self.prepareVolnOp('xyzc', 4)

            # Specify a strange order for the output axis tags
            self.operator.AxisOrder.setValue('yxtzc')
            shape = self.operator.Output.meta.shape

            roi = [None, None]
            roi[1] = [
                numpy.random.randint(2, s) if s != 1 else 1 for s in shape
            ]
            roi[0] = [
                numpy.random.randint(0, roi[1][i]) if s != 1 else 0
                for i, s in enumerate(shape)
            ]
            roi[0] = TinyVector(roi[0])
            roi[1] = TinyVector(roi[1])
            result = self.operator.Output(roi[0], roi[1]).wait()
            logger.debug(
                '------------------------------------------------------')
            logger.debug("self.array.shape = " + str(self.array.shape))
            logger.debug("type(input) == " +
                         str(type(self.operator.Input.value)))
            logger.debug("input.shape == " +
                         str(self.operator.Input.meta.shape))
            logger.debug("Input Tags:")
            logger.debug(str(self.operator.Input.meta.axistags))
            logger.debug("Output Tags:")
            logger.debug(str(self.operator.Output.meta.axistags))
            logger.debug("roi= " + str(roi))
            logger.debug("type(result) == " + str(type(result)))
            logger.debug("result.shape == " + str(result.shape))
            logger.debug(
                '------------------------------------------------------')

            # Check the shape
            assert len(result.shape) == 5

            assert not isinstance(result, vigra.VigraArray), \
                "For compatibility with generic code, output should be provided as a plain numpy array."

            # Ensure the result came out in the same strange order we asked for.
            assert self.operator.Output.meta.axistags == vigra.defaultAxistags(
                'yxtzc')

            # Check the data
            vresult = result.view(vigra.VigraArray)
            vresult.axistags = self.operator.Output.meta.axistags
            reorderedInput = self.inArray.withAxes(
                *[tag.key for tag in self.operator.Output.meta.axistags])
            assert numpy.all(
                vresult == reorderedInput[roiToSlice(roi[0], roi[1])])
Esempio n. 16
0
        def test_Roi_custom_order(self):
            for i in range(self.tests):
                self.prepareVolnOp()

                # Specify a strange order for the output axis tags
                self.operator.order.setValue('ctyzx')
                shape = self.operator.outputs["output"].meta.shape

                roi = [None, None]
                roi[1] = [
                    numpy.random.randint(2, s) if s != 1 else 1 for s in shape
                ]
                roi[0] = [
                    numpy.random.randint(0, roi[1][i]) if s != 1 else 0
                    for i, s in enumerate(shape)
                ]
                roi[0] = TinyVector(roi[0])
                roi[1] = TinyVector(roi[1])
                result = self.operator.outputs["output"](roi[0], roi[1]).wait()
                logger.debug(
                    '------------------------------------------------------')
                logger.debug("self.array.shape = " + str(self.array.shape))
                logger.debug("type(input) == " +
                             str(type(self.operator.input.value)))
                logger.debug("input.shape == " +
                             str(self.operator.input.meta.shape))
                logger.debug("Input Tags:")
                logger.debug(str(self.operator.inputs['input'].meta.axistags))
                logger.debug("Output Tags:")
                logger.debug(str(self.operator.output.meta.axistags))
                logger.debug("roi= " + str(roi))
                logger.debug("type(result) == " + str(type(result)))
                logger.debug("result.shape == " + str(result.shape))
                logger.debug(
                    '------------------------------------------------------')

                # Check the shape
                assert len(result.shape) == 5

                # Ensure the result came out in the same strange order we asked for.
                assert self.operator.outputs[
                    "output"].meta.axistags == vigra.defaultAxistags('ctyzx')

                # Check the data
                vresult = result.view(vigra.VigraArray)
                vresult.axistags = self.operator.outputs[
                    "output"].meta.axistags
                reorderedInput = self.inArray.withAxes(*[
                    tag.key
                    for tag in self.operator.outputs["output"].meta.axistags
                ])
                assert numpy.all(
                    vresult == reorderedInput[roiToSlice(roi[0], roi[1])])
Esempio n. 17
0
    def _getInputComputeRois(self, roi):
        axiskeys = self.Input.meta.getAxisKeys()
        spatialkeys = [k for k in axiskeys if k in 'zyx']
        sigma = list(map(self._sigmas.get, spatialkeys))
        inputSpatialShape = self.Input.meta.getTaggedShape()
        spatialRoi = (TinyVector(roi.start), TinyVector(roi.stop))
        tIndex = None
        cIndex = None
        zIndex = None
        if 'c' in inputSpatialShape:
            del inputSpatialShape['c']
            cIndex = axiskeys.index('c')
        if 't' in list(inputSpatialShape.keys()):
            assert inputSpatialShape['t'] == 1
            tIndex = axiskeys.index('t')

        if 'z' in list(
                inputSpatialShape.keys()) and inputSpatialShape['z'] == 1:
            #2D image, avoid kernel longer than line exception
            del inputSpatialShape['z']
            zIndex = axiskeys.index('z')

        indices = [tIndex, cIndex, zIndex]
        indices = sorted(indices, reverse=True)
        for ind in indices:
            if ind:
                spatialRoi[0].pop(ind)
                spatialRoi[1].pop(ind)

        inputSpatialRoi = enlargeRoiForHalo(spatialRoi[0],
                                            spatialRoi[1],
                                            list(inputSpatialShape.values()),
                                            sigma,
                                            window=2.0)

        # Determine the roi within the input data we're going to request
        inputRoiOffset = spatialRoi[0] - inputSpatialRoi[0]
        computeRoi = (inputRoiOffset,
                      inputRoiOffset + spatialRoi[1] - spatialRoi[0])

        # For some reason, vigra.filters.gaussianSmoothing will raise an exception if this parameter doesn't have the correct integer type.
        # (for example, if we give it as a numpy.ndarray with dtype=int64, we get an error)
        computeRoi = (tuple(map(int,
                                computeRoi[0])), tuple(map(int,
                                                           computeRoi[1])))

        inputRoi = (list(inputSpatialRoi[0]), list(inputSpatialRoi[1]))
        for ind in reversed(indices):
            if ind:
                inputRoi[0].insert(ind, 0)
                inputRoi[1].insert(ind, 1)

        return inputRoi, computeRoi
Esempio n. 18
0
    def _deserialize(self, mygroup, slot):
        num = len(mygroup)
        if len(self.inslot) < num:
            self.inslot.resize(num)
        for index, t in enumerate(sorted(mygroup.items())):
            groupName, labelGroup = t
            for blockRoiString, blockDataset in labelGroup.items():
                blockRoi = eval(blockRoiString)
                roiShape = TinyVector(blockRoi[1]) - TinyVector(blockRoi[0])
                assert roiShape == blockDataset.shape

                self.inslot[index][roiToSlice(*blockRoi)] = blockDataset
Esempio n. 19
0
 def adjustChannel(self, start, stop, cPerC, cIndex):
     if cPerC != 1:
         start = [
             start[i] / cPerC if i == cIndex else start[i]
             for i in range(len(start))
         ]
         stop = [
             stop[i] / cPerC + 1 if i == cIndex else stop[i]
             for i in range(len(stop))
         ]
         start = TinyVector(start)
         stop = TinyVector(stop)
     return start, stop
Esempio n. 20
0
    def execute(self, slot, subindex, roi, result):
        assert slot == self.Output, "Unknown slot: {}".format( slot.name )
        radius = self.CrosshairRadius.value
        points = map(TinyVector, self.PointList.value)
        
        result[:] = 0
        result_view = result.view(vigra.VigraArray)
        result_view.axistags = self.Output.meta.axistags
        result_3d = result_view.withAxes(*'xyz')

        axiskeys = self.Output.meta.getAxisKeys()
        roi_start_3d = TinyVector(roi.start)
        roi_stop_3d = TinyVector(roi.stop)
        try:
            roi_start_3d.pop( axiskeys.index('c') )
            roi_stop_3d.pop( axiskeys.index('c') )
        except ValueError:
            pass

        try:        
            roi_start_3d.pop( axiskeys.index('t') )
            roi_stop_3d.pop( axiskeys.index('t') )
        except ValueError:
            pass

        for point3d in points:
            point3d -= roi_start_3d
            
            cross_min = point3d - radius
            cross_max = point3d + radius+1
            
            # If the cross would be entirely out-of-view, skip it.
            if (cross_max < [0,0,0]).any() or \
               (cross_min >= result_3d.shape).any():
                continue

            cross_min = numpy.maximum(cross_min, (0,0,0))
            cross_max = numpy.minimum(cross_max, result_3d.shape)

            x,y,z = point3d
            x1,y1,z1 = cross_min
            x2,y2,z2 = cross_max

            if 0 <= y < result_3d.shape[1] and 0 <= z < result_3d.shape[2]:
                result_3d[x1:x2, y,     z    ] = 1
            if 0 <= x < result_3d.shape[0] and 0 <= z < result_3d.shape[2]:
                result_3d[x,     y1:y2, z    ] = 1
            if 0 <= x < result_3d.shape[0] and 0 <= y < result_3d.shape[1]:
                result_3d[x,     y,     z1:z2] = 1

        return result
Esempio n. 21
0
def generateRandomRoi(maxShape,minShape = 0,minWidth = 0):
    """
    for a given shape of any dimension this method returns a roi which is
    bounded by maxShape and minShape and has the minimum Width in minWidth
    in all dimensions
    """
    if not minShape:
        minShape = tuple(numpy.zeros_like(maxShape))
    assert len(maxShape) == len(minShape),'Dimensions of Shape do not match!'
    roi = [[0,0]]
    while len([x for x in roi if not abs(x[0]-x[1]) < minWidth]) < len(maxShape):
        roi = [sorted([numpy.random.randint(minDim,maxDim),numpy.random.randint(minDim,maxDim)]) for minDim,maxDim in zip(minShape,maxShape)]
    roi = [TinyVector([x[0] for x in roi]),TinyVector([x[1] for x in roi])]
    return roi
Esempio n. 22
0
 def adjustChannel(self, cPerC, cIndex, channelRes):
     assert sys.version_info.major == 2, "Alert! This function has not been tested "\
     "under python 3. Please remove this assetion and be wary of any strange behavior you encounter"
     if cPerC != 1 and channelRes == 1:
         start = [
             self.start[i] // cPerC if i == cIndex else self.start[i]
             for i in range(len(self.start))
         ]
         stop = [
             self.stop[i] // cPerC + 1 if i == cIndex else self.stop[i]
             for i in range(len(self.stop))
         ]
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     elif channelRes > 1:
         start = [
             0 if i == cIndex else self.start[i]
             for i in range(len(self.start))
         ]
         stop = [
             channelRes if i == cIndex else self.stop[i]
             for i in range(len(self.stop))
         ]
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     return self
Esempio n. 23
0
    def execute(self, slot, subindex, roi, result):
        assert all(roi.stop <= self.Input.meta.shape), "Requested roi {} is too large for this input image of shape {}.".format( roi, self.Input.meta.shape )
        # Determine how much input data we'll need, and where the result will be relative to that input roi
        inputRoi, computeRoi = self._getInputComputeRois(roi)        
        # Obtain the input data 
        with Timer() as resultTimer:
            data = self.Input( *inputRoi ).wait()
        logger.debug("Obtaining input data took {} seconds for roi {}".format( resultTimer.seconds(), inputRoi ))
        
        xIndex = self.Input.meta.axistags.index('x')
        yIndex = self.Input.meta.axistags.index('y')
        zIndex = self.Input.meta.axistags.index('z') if self.Input.meta.axistags.index('z')<len(self.Input.meta.shape) else None
        cIndex = self.Input.meta.axistags.index('c') if self.Input.meta.axistags.index('c')<len(self.Input.meta.shape) else None
        
        # Must be float32
        if data.dtype != numpy.float32:
            data = data.astype(numpy.float32)
        
        axiskeys = self.Input.meta.getAxisKeys()
        spatialkeys = filter( lambda k: k in 'xyz', axiskeys )

        # we need to remove a singleton z axis, otherwise we get 
        # 'kernel longer than line' errors
        reskey = [slice(None, None, None)]*len(self.Input.meta.shape)
        reskey[cIndex]=0
        if zIndex and self.Input.meta.shape[zIndex]==1:
            removedZ = True
            data = data.reshape((data.shape[xIndex], data.shape[yIndex]))
            reskey[zIndex]=0
            spatialkeys = filter( lambda k: k in 'xy', axiskeys )
        else:
            removedZ = False

        sigma = map(self._sigmas.get, spatialkeys)
        #Check if we need to smooth
        if any([x < 0.1 for x in sigma]):
            if removedZ:
                resultXY = vigra.taggedView(result, axistags="".join(axiskeys))
                resultXY = resultXY.withAxes(*'xy')
                resultXY[:] = data
            else:
                result[:] = data
            return result

        # Smooth the input data
        smoothed = vigra.filters.gaussianSmoothing(data, sigma, window_size=2.0, roi=computeRoi, out=result[tuple(reskey)]) # FIXME: Assumes channel is last axis
        expectedShape = tuple(TinyVector(computeRoi[1]) - TinyVector(computeRoi[0]))
        assert tuple(smoothed.shape) == expectedShape, "Smoothed data shape {} didn't match expected shape {}".format( smoothed.shape, roi.stop - roi.start )
        
        return result
Esempio n. 24
0
 def adjustChannel(self,cPerC,cIndex,channelRes):
     assert sys.version_info.major == 2, "Alert! This function has not been tested "\
     "under python 3. Please remove this assetion and be wary of any strange behavior you encounter"
     if cPerC != 1 and channelRes == 1:
         start = [self.start[i]//cPerC if i == cIndex else self.start[i] for i in range(len(self.start))]
         stop = [self.stop[i]//cPerC+1 if i==cIndex else self.stop[i] for i in range(len(self.stop))]
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     elif channelRes > 1:
         start = [0 if i == cIndex else self.start[i] for i in range(len(self.start))]
         stop = [channelRes if i==cIndex else self.stop[i] for i in range(len(self.stop))]
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     return self
Esempio n. 25
0
    def handleAppletStateUpdateRequested(self):
        """
        Overridden from Workflow base class
        Called when an applet has fired the :py:attr:`Applet.statusUpdateSignal`
        """
        opDataSelection = self.dataSelectionApplet.topLevelOperator
        input_ready = len(opDataSelection.ImageGroup) > 0

        opDataExport = self.dataExportApplet.topLevelOperator
        export_data_ready = (
            input_ready
            and len(opDataExport.Inputs[0]) > 0
            and opDataExport.Inputs[0][0].ready()
            and (TinyVector(opDataExport.Inputs[0][0].meta.shape) > 0).all()
        )

        self._shell.setAppletEnabled(self.dataSelectionApplet, not self.batchProcessingApplet.busy)
        self._shell.setAppletEnabled(self.dataExportApplet, export_data_ready and not self.batchProcessingApplet.busy)
        self._shell.setAppletEnabled(self.batchProcessingApplet, export_data_ready)

        # Lastly, check for certain "busy" conditions, during which we
        #  should prevent the shell from closing the project.
        busy = False
        busy |= self.dataSelectionApplet.busy
        busy |= self.dataExportApplet.busy
        busy |= self.batchProcessingApplet.busy
        self._shell.enableProjectChanges(not busy)
Esempio n. 26
0
    def _executeCleanBlocks(self, destination):
        """
        Execute function for the CleanBlocks output slot, which produces
        an *unsorted* list of block rois that the cache currently holds.
        """
        # Set difference: clean = existing - dirty
        clean_block_starts = set(self._cacheFiles.keys()) - self._dirtyBlocks

        output_shape = self.Output.meta.shape
        clean_block_rois = list(
            map(partial(getBlockBounds, output_shape, self._blockshape),
                clean_block_starts))
        results = []
        for cbr in clean_block_rois:
            results.append([TinyVector(cbr[0]), TinyVector(cbr[1])])
        destination[0] = results
        return destination
Esempio n. 27
0
    def _checkUnaryOperation(self, op):
        v1 = self.v1
        nv1 = TinyVector(-x for x in v1)
        a1 = numpy.array(v1)
        na1 = numpy.array(nv1)

        assert all(op(v1) == op(a1))
        assert all(op(nv1) == op(na1))
Esempio n. 28
0
 def setupOutputs(self):
     self._propagate_dirty = self.propagate_dirty.value
     start = self.inputs["Start"].value
     stop = self.inputs["Stop"].value
     assert isinstance(start, tuple)
     assert isinstance(stop, tuple)
     assert len(start) == len(self.inputs["Input"].meta.shape)
     assert len(start) == len(stop)
     assert (numpy.array(stop)>= numpy.array(start)).all()
 
     out_shape = TinyVector(stop) - TinyVector(start)
     if (out_shape <= 0).any():
         self.Output.meta.NOTREADY = True
     else:
         self.Output.meta.assignFrom(self.Input.meta)
         self.Output.meta.shape = tuple(out_shape)
         if self.Input.meta.drange is not None:
             self.Output.meta.drange = self.Input.meta.drange
Esempio n. 29
0
 def __init__(self, slot, start = None, stop = None, pslice = None):
     super(SubRegion,self).__init__(slot)
     if pslice != None or start is not None and stop is None and pslice is None:
         if pslice is None:
             pslice = start
         shape = self.slot.meta.shape
         if shape is None:
             # Okay to use a shapeless slot if the key is bounded
             # AND if the key has the correct length
             assert slicingtools.is_bounded(pslice)
             # Supply a dummy shape
             shape = [0] * len(pslice)
         self.start, self.stop = sliceToRoi(pslice,shape)
     elif start is None and pslice is None:
         self.start, self.stop = sliceToRoi(slice(None,None,None),self.slot.meta.shape)
     else:
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     self.dim = len(self.start)
Esempio n. 30
0
 def adjustChannel(self,cPerC,cIndex,channelRes):
     if cPerC != 1 and channelRes == 1:
         start = [self.start[i]/cPerC if i == cIndex else self.start[i] for i in range(len(self.start))]
         stop = [self.stop[i]/cPerC+1 if i==cIndex else self.stop[i] for i in range(len(self.stop))]
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     elif channelRes > 1:
         start = [0 if i == cIndex else self.start[i] for i in range(len(self.start))]
         stop = [channelRes if i==cIndex else self.stop[i] for i in range(len(self.stop))]
         self.start = TinyVector(start)
         self.stop = TinyVector(stop)
     return self
Esempio n. 31
0
 def testAny(self):
     a = TinyVector([True, True, True])
     b = TinyVector([True, False, True])
     c = TinyVector([False, False, False])
     assert a.any()
     assert b.any()
     assert not c.any()
Esempio n. 32
0
    def handleAppletStateUpdateRequested(self):
        """
        Overridden from Workflow base class
        Called when an applet has fired the :py:attr:`Applet.appletStateUpdateRequested`
        """
        # If no data, nothing else is ready.
        opDataSelection = self.dataSelectionApplet.topLevelOperator
        input_ready = len(opDataSelection.ImageGroup) > 0 and not self.dataSelectionApplet.busy

        opDLClassification = self.dlClassificationApplet.topLevelOperator

        opDataExport = self.dataExportApplet.topLevelOperator

        predictions_ready = (
            input_ready
            and len(opDataExport.Inputs) > 0
            and opDataExport.Inputs[0][0].ready()
            and (TinyVector(opDataExport.Inputs[0][0].meta.shape) > 0).all()
        )

        # Problems can occur if the input data is changed during live update mode.
        # Don't let the user do that.
        live_update_active = not opDLClassification.FreezePredictions.value

        # The user isn't allowed to touch anything while batch processing is running.
        batch_processing_busy = False  # self.batchProcessingApplet.busy

        self._shell.setAppletEnabled(self.dataSelectionApplet, not live_update_active and not batch_processing_busy)
        self._shell.setAppletEnabled(self.dlClassificationApplet, input_ready and not batch_processing_busy)
        self._shell.setAppletEnabled(self.dataExportApplet, predictions_ready and not batch_processing_busy)

        # if self.batchProcessingApplet is not None:
        #     self._shell.setAppletEnabled(self.batchProcessingApplet, predictions_ready and not batch_processing_busy)

        # Lastly, check for certain "busy" conditions, during which we
        # should prevent the shell from closing the project.
        busy = False
        busy |= self.dataSelectionApplet.busy
        busy |= self.dlClassificationApplet.busy
        busy |= self.dataExportApplet.busy
        # busy |= self.batchProcessingApplet.busy
        self._shell.enableProjectChanges(not busy)
Esempio n. 33
0
class SubRegion(Roi):
    def __init__(self, slot, start=None, stop=None, pslice=None):
        super(SubRegion, self).__init__(slot)
        if pslice != None or start is not None and stop is None and pslice is None:
            if pslice is None:
                pslice = start
            shape = self.slot.meta.shape
            if shape is None:
                # Okay to use a shapeless slot if the key is bounded
                # AND if the key has the correct length
                assert slicingtools.is_bounded(pslice)
                # Supply a dummy shape
                shape = [0] * len(pslice)
            self.start, self.stop = sliceToRoi(pslice, shape)
        elif start is None and pslice is None:
            self.start, self.stop = sliceToRoi(slice(None, None, None), self.slot.meta.shape)
        else:
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        self.dim = len(self.start)

    def __str__(self):
        return "".join(("Subregion: start '", str(self.start), "' stop '", str(self.stop), "'"))

    @staticmethod
    def _toString(roi):
        assert isinstance(roi, SubRegion)
        assert roi.slot is None, "Can't stringify SubRegions with no slot"
        return "SubRegion(None, {}, {})".format(roi.start, roi.stop)

    @staticmethod
    def _fromString(s):
        return eval(s)

    def setInputShape(self, inputShape):
        assert type(inputShape) == tuple
        self.inputShape = inputShape

    def copy(self):
        return copy.copy(self)

    def popDim(self, dim):
        """
        remove the i'th dimension from the SubRegion
        works inplace !
        """
        if dim is not None:
            self.start.pop(dim)
            self.stop.pop(dim)
        return self

    def setDim(self, dim, start, stop):
        """
        change the subarray at dim, to begin at start
        and to end at stop
        """
        self.start[dim] = start
        self.stop[dim] = stop
        return self

    def insertDim(self, dim, start, stop, at):
        """
        insert a new dimension before dim.
        set start to start, stop to stop
        and the axistags to at
        """
        self.start.insert(0, start)
        self.stop.insert(0, stop)
        return self

    def expandByShape(self, shape, cIndex, tIndex):
        """
        extend a roi by a given in shape
        """
        # TODO: Warn if bounds are exceeded
        cStart = self.start[cIndex]
        cStop = self.stop[cIndex]
        if tIndex is not None:
            tStart = self.start[tIndex]
            tStop = self.stop[tIndex]
        if isinstance(shape, collections.Iterable):
            # add a dummy number for the channel dimension
            shape = shape + (1,)
        else:
            tmp = shape
            shape = numpy.zeros(self.dim).astype(int)
            shape[:] = tmp

        tmpStart = [int(x - s) for x, s in zip(self.start, shape)]
        tmpStop = [int(x + s) for x, s in zip(self.stop, shape)]
        start = [int(max(t, i)) for t, i in zip(tmpStart, numpy.zeros_like(self.inputShape))]
        stop = [int(min(t, i)) for t, i in zip(tmpStop, self.inputShape)]
        start[cIndex] = cStart
        stop[cIndex] = cStop
        if tIndex is not None:
            start[tIndex] = tStart
            stop[tIndex] = tStop
        self.start = TinyVector(start)
        self.stop = TinyVector(stop)
        return self

    def adjustRoi(self, halo, cIndex=None):
        if type(halo) != list:
            halo = [halo] * len(self.start)
        notAtStartEgde = map(lambda x, y: True if x < y else False, halo, self.start)
        for i in range(len(notAtStartEgde)):
            if notAtStartEgde[i]:
                self.stop[i] = int(self.stop[i] - self.start[i] + halo[i])
                self.start[i] = int(halo[i])
        return self

    def adjustChannel(self, cPerC, cIndex, channelRes):
        if cPerC != 1 and channelRes == 1:
            start = [self.start[i] / cPerC if i == cIndex else self.start[i] for i in range(len(self.start))]
            stop = [self.stop[i] / cPerC + 1 if i == cIndex else self.stop[i] for i in range(len(self.stop))]
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        elif channelRes > 1:
            start = [0 if i == cIndex else self.start[i] for i in range(len(self.start))]
            stop = [channelRes if i == cIndex else self.stop[i] for i in range(len(self.stop))]
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        return self

    def toSlice(self, hardBind=False):
        return roiToSlice(self.start, self.stop, hardBind)
    def _executeProjection2D(self, roi, destination):
        assert sum(TinyVector(destination.shape) > 1) <= 2, "Projection result must be exactly 2D"
        
        # First, we have to determine which axis we are projecting along.
        # We infer this from the shape of the roi.
        # For example, if the roi is of shape 
        #  zyx = (1,256,256), then we know we're projecting along Z
        # If more than one axis has a width of 1, then we choose an 
        #  axis according to the following priority order: zyxt
        tagged_input_shape = self.Input.meta.getTaggedShape()
        tagged_result_shape = collections.OrderedDict( zip( tagged_input_shape.keys(),
                                                            destination.shape ) )
        nonprojection_axes = []
        for key in tagged_input_shape.keys():
            if (key == 'c' or tagged_input_shape[key] == 1 or tagged_result_shape[key] > 1):
                nonprojection_axes.append( key )
            
        possible_projection_axes = set(tagged_input_shape) - set(nonprojection_axes)
        if len(possible_projection_axes) == 0:
            # If the image is 2D to begin with, 
            #   then the projection is simply the same as the normal output,
            #   EXCEPT it is made binary
            self.Output(roi.start, roi.stop).writeInto(destination).wait()
            
            # make binary
            numpy.greater(destination, 0, out=destination)
            return
        
        for k in 'zyxt':
            if k in possible_projection_axes:
                projection_axis_key = k
                break

        # Now we know which axis we're projecting along.
        # Proceed with the projection, working blockwise to avoid unecessary work in unlabeled blocks
        
        projection_axis_index = self.Input.meta.getAxisKeys().index(projection_axis_key)
        projection_length = tagged_input_shape[projection_axis_key]
        input_roi = roi.copy()
        input_roi.start[projection_axis_index] = 0
        input_roi.stop[projection_axis_index] = projection_length

        destination[:] = 0.0

        # Get the logical blocking.
        block_starts = getIntersectingBlocks( self._blockshape, (input_roi.start, input_roi.stop) )

        # (Parallelism wouldn't help here: h5py will serialize these requests anyway)
        block_starts = map( tuple, block_starts )
        for block_start in block_starts:
            if block_start not in self._cacheFiles:
                # No label data in this block.  Move on.
                continue

            entire_block_roi = getBlockBounds( self.Output.meta.shape, self._blockshape, block_start )

            # This block's portion of the roi
            intersecting_roi = getIntersection( (input_roi.start, input_roi.stop), entire_block_roi )
            
            # Compute slicing within the deep array and slicing within this block
            deep_relative_intersection = numpy.subtract(intersecting_roi, input_roi.start)
            block_relative_intersection = numpy.subtract(intersecting_roi, block_start)
                        
            deep_data = self._getBlockDataset( entire_block_roi )[roiToSlice(*block_relative_intersection)]

            # make binary and convert to float
            deep_data_float = numpy.where( deep_data, numpy.float32(1.0), numpy.float32(0.0) )
            
            # multiply by slice-index
            deep_data_view = numpy.rollaxis(deep_data_float, projection_axis_index, 0)

            min_deep_slice_index = deep_relative_intersection[0][projection_axis_index]
            max_deep_slice_index = deep_relative_intersection[1][projection_axis_index]
            
            def calc_color_value(slice_index):
                # Note 1: We assume that the colortable has at least 256 entries in it,
                #           so, we try to ensure that all colors are above 1/256 
                #           (we don't want colors in low slices to be rounded to 0)
                # Note 2: Ideally, we'd use a min projection in the code below, so that 
                #           labels in the "back" slices would appear occluded.  But the 
                #           min projection would favor 0.0.  Instead, we invert the 
                #           relationship between color and slice index, do a max projection, 
                #           and then re-invert the colors after everything is done.
                #           Hence, this function starts with (1.0 - ...)
                return (1.0 - (float(slice_index) / projection_length)) * (1.0 - 1.0/255) + 1.0/255.0
            min_color_value = calc_color_value(min_deep_slice_index)
            max_color_value = calc_color_value(max_deep_slice_index)
            
            num_slices = max_deep_slice_index - min_deep_slice_index
            deep_data_view *= numpy.linspace( min_color_value, max_color_value, num=num_slices )\
                              [ (slice(None),) + (None,)*(deep_data_view.ndim-1) ]

            # Take the max projection of this block's data.
            block_max_projection = numpy.amax(deep_data_float, axis=projection_axis_index, keepdims=True)

            # Merge this block's projection into the overall projection.
            destination_relative_intersection = numpy.array(deep_relative_intersection)
            destination_relative_intersection[:, projection_axis_index] = (0,1)            
            destination_subview = destination[roiToSlice(*destination_relative_intersection)]            
            numpy.maximum(block_max_projection, destination_subview, out=destination_subview)
            
            # Invert the nonzero pixels so increasing colors correspond to increasing slices.
            # See comment in calc_color_value(), above.
            destination_subview[:] = numpy.where(destination_subview, 
                                                 numpy.float32(1.0) - destination_subview, 
                                                 numpy.float32(0.0))
        return
Esempio n. 35
0
class SubRegion(Roi):
    def __init__(self, slot, start = None, stop = None, pslice = None):
        super(SubRegion,self).__init__(slot)
        shape = None
        if slot is not None:
            shape = slot.meta.shape
        if pslice != None or start is not None and stop is None and pslice is None:
            if pslice is None:
                pslice = start
            if shape is None:
                # Okay to use a shapeless slot if the key is bounded
                # AND if the key has the correct length
                assert slicingtools.is_bounded(pslice)
                # Supply a dummy shape
                shape = [0] * len(pslice)
            self.start, self.stop = sliceToRoi(pslice,shape)
        elif start is None and pslice is None:
            assert shape is not None, "Can't create a default subregion without a slot and a shape."
            self.start, self.stop = roiFromShape(shape)
        else:
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        self.dim = len(self.start)

        for start, stop in zip(self.start, self.stop):
            assert isinstance(start, (int, long, numpy.integer)), "Roi contains non-integers: {}".format( self )
            assert isinstance(start, (int, long, numpy.integer)), "Roi contains non-integers: {}".format( self )

# FIXME: This assertion is good at finding bugs, but it is currently triggered by 
#        the DataExport applet when the output axis order is changed. 
# 
#         if self.slot is not None self.slot.meta.shape is not None:
#             assert all(self.stop <= self.slot.meta.shape), \
#                 "Roi is out of bounds. roi={}, {}.{}.meta.shape={}"\
#                 .format((self.start, self.stop), slot.getRealOperator().name, slot.name, self.slot.meta.shape)

    def __setstate__(self, state):
        """
        Support copy.copy()
        """
        self.slot = state['slot']
        self.start = TinyVector( state['start'] )
        self.stop = TinyVector( state['stop'] )
        self.dim = len( state['start'] )

    def __str__( self ):
        return "".join(("Subregion: start '", str(self.start), "' stop '", str(self.stop), "'"))
    
    def pprint(self):
        """pretty-print this object"""
        ret = ""
        for a,b in zip(self.start, self.stop):
            ret += "%d-%d " % (a,b)
        return ret

    @staticmethod
    def _toString(roi):
        assert isinstance(roi, SubRegion)
        assert roi.slot is None, "Can't stringify SubRegions with no slot"
        return "SubRegion(None, {}, {})".format(roi.start, roi.stop)

    @staticmethod
    def _fromString(s):
        return eval(s)

    def setInputShape(self,inputShape):
        assert type(inputShape) == tuple
        self.inputShape = inputShape

    def copy(self):
        return copy.copy(self)

    def popDim(self, dim):
        """
        remove the i'th dimension from the SubRegion
        works inplace !
        """
        if dim is not None:
            self.start.pop(dim)
            self.stop.pop(dim)
        return self

    def setDim(self, dim , start, stop):
        """
        change the subarray at dim, to begin at start
        and to end at stop
        """
        self.start[dim] = start
        self.stop[dim] = stop
        return self

    def insertDim(self, dim, start, stop):
        """
        insert a new dimension before dim.
        set start to start, stop to stop
        and the axistags to at
        """
        self.start = self.start.insert(dim,start)
        self.stop = self.stop.insert(dim,stop)
        return self
        

    def expandByShape(self,shape,cIndex,tIndex):
        """
        extend a roi by a given in shape
        """
        #TODO: Warn if bounds are exceeded
        cStart = self.start[cIndex]
        cStop = self.stop[cIndex]
        if tIndex is not None:
            tStart = self.start[tIndex]
            tStop = self.stop[tIndex]
        if isinstance(shape, collections.Iterable):
            #add a dummy number for the channel dimension
            shape = shape+(1,)
        else:
            tmp = shape
            shape = numpy.zeros(self.dim).astype(int)
            shape[:] = tmp
        
        tmpStart = [int(x-s) for x,s in zip(self.start,shape)]
        tmpStop = [int(x+s) for x,s in zip(self.stop,shape)]
        start = [int(max(t,i)) for t,i in zip(tmpStart,numpy.zeros_like(self.inputShape))]   
        stop = [int(min(t,i)) for t,i in zip(tmpStop,self.inputShape)]
        start[cIndex] = cStart
        stop[cIndex] = cStop
        if tIndex is not None:
            start[tIndex] = tStart
            stop[tIndex] = tStop
        self.start = TinyVector(start)
        self.stop = TinyVector(stop)
        return self
        
    def adjustRoi(self,halo,cIndex=None):
        if type(halo) != list:
            halo = [halo]*len(self.start)
        notAtStartEgde = map(lambda x,y: True if x<y else False,halo,self.start)
        for i in range(len(notAtStartEgde)):
            if notAtStartEgde[i]:
                self.stop[i] = int(self.stop[i]-self.start[i]+halo[i])
                self.start[i] = int(halo[i])
        return self

    def adjustChannel(self,cPerC,cIndex,channelRes):
        if cPerC != 1 and channelRes == 1:
            start = [self.start[i]/cPerC if i == cIndex else self.start[i] for i in range(len(self.start))]
            stop = [self.stop[i]/cPerC+1 if i==cIndex else self.stop[i] for i in range(len(self.stop))]
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        elif channelRes > 1:
            start = [0 if i == cIndex else self.start[i] for i in range(len(self.start))]
            stop = [channelRes if i==cIndex else self.stop[i] for i in range(len(self.stop))]
            self.start = TinyVector(start)
            self.stop = TinyVector(stop)
        return self

    def toSlice(self, hardBind = False):
        return roiToSlice(self.start,self.stop, hardBind)
    def _parseAnnotationFile(cls, annotation_filepath, body_label_img_slot):
        """
        Returns dict of annotations of the form { coordinate_3d : Annotation }
        """
        try:
            with open(annotation_filepath) as annotationFile:
                annotation_json_dict = json.load(annotationFile)
        except Exception as ex:
            raise cls.AnnotationParsingException(
                "Failed to parse your bookmark file.  It isn't valid JSON.",
                ex), None, sys.exc_info()[2]

        if 'data' not in annotation_json_dict:
            raise cls.AnnotationParsingException(
                "Couldn't find the 'data' list in your bookmark file.  Giving up."
            ), None, sys.exc_info()[2]

        # Before we parse the bookmarks data, locate the substack description
        #  to calculate the z-coordinate offset (see comment about substack coordinates, above)
        bookmark_dir = os.path.split(annotation_filepath)[0]
        substack_dir = os.path.split(bookmark_dir)[0]
        substack_description_path = os.path.join(substack_dir, 'substack.json')
        try:
            with open(substack_description_path) as substack_description_file:
                substack_description_json_dict = json.load(
                    substack_description_file)
        except Exception as ex:
            raise cls.AnnotationParsingException(
                "Failed to parse SUBSTACK",
                "Attempted to open substack description file:\n {}"
                "\n but something went wrong.  See console output for details.  Giving up."
                .format(substack_description_path)), None, sys.exc_info()[2]

        # See comment above about why we have to subtract a Z-offset
        z_offset = substack_description_json_dict[
            'idz1'] - substack_description_json_dict['border']

        # Each bookmark is a dict (see example above)
        annotations = {}
        bookmarks = annotation_json_dict['data']
        for bookmark in bookmarks:
            if 'text' in bookmark and str(
                    bookmark['text']).lower().find('split') != -1:
                coord3d = bookmark['location']
                coord3d[1] = 520 - coord3d[
                    1]  # Raveler y-axis is inverted (Raveler substacks are 520 cubes)
                coord3d[
                    2] -= z_offset  # See comments above re: substack coordinates
                coord3d = tuple(coord3d)
                coord5d = (0, ) + coord3d + (0, )
                pos = TinyVector(coord5d)
                sample_roi = (pos, pos + 1)
                # For debug purposes, we sometimes load a smaller volume than the original.
                # Don't import bookmarks that fall outside our volume
                if (pos < body_label_img_slot.meta.shape).all():
                    # Sample the label volume to determine the body id (raveler label)
                    label_sample = body_label_img_slot(*sample_roi).wait()
                    annotations[coord3d] = OpParseAnnotations.Annotation(
                        ravelerLabel=label_sample[0, 0, 0, 0, 0],
                        comment=str(bookmark['text']))

        return annotations
Esempio n. 37
0
    def handleAppletStateUpdateRequested(self):
        """
        Overridden from Workflow base class
        Called when an applet has fired the :py:attr:`Applet.appletStateUpdateRequested`
        """
        # If no data, nothing else is ready.
        opDataSelection = self.dataSelectionApplet.topLevelOperator
        input_ready = len(opDataSelection.ImageGroup
                          ) > 0 and not self.dataSelectionApplet.busy

        # First, determine various 'ready' states for each pixel classification stage (features+prediction)
        StageFlags = collections.namedtuple(
            "StageFlags",
            "input_ready features_ready invalid_classifier predictions_ready live_update_active"
        )
        stage_flags = []
        for stage_index, (featureSelectionApplet, pcApplet) in enumerate(
                zip(self.featureSelectionApplets, self.pcApplets)):
            if stage_index == 0:
                input_ready = len(opDataSelection.ImageGroup
                                  ) > 0 and not self.dataSelectionApplet.busy
            else:
                input_ready = stage_flags[stage_index - 1].predictions_ready

            opFeatureSelection = featureSelectionApplet.topLevelOperator
            featureOutput = opFeatureSelection.OutputImage
            features_ready = (
                input_ready and len(featureOutput) > 0
                and featureOutput[0].ready()
                and (TinyVector(featureOutput[0].meta.shape) > 0).all())

            opPixelClassification = pcApplet.topLevelOperator
            invalid_classifier = (
                opPixelClassification.classifier_cache.fixAtCurrent.value
                and opPixelClassification.classifier_cache.Output.ready() and
                opPixelClassification.classifier_cache.Output.value is None)

            predictions_ready = (
                features_ready and not invalid_classifier and
                len(opPixelClassification.HeadlessPredictionProbabilities) > 0
                and opPixelClassification.HeadlessPredictionProbabilities[0].
                ready() and (TinyVector(
                    opPixelClassification.HeadlessPredictionProbabilities[0].
                    meta.shape) > 0).all())

            live_update_active = not opPixelClassification.FreezePredictions.value

            stage_flags += [
                StageFlags(input_ready, features_ready, invalid_classifier,
                           predictions_ready, live_update_active)
            ]

        opDataExport = self.dataExportApplet.topLevelOperator
        opPixelClassification = self.pcApplets[0].topLevelOperator

        # Problems can occur if the features or input data are changed during live update mode.
        # Don't let the user do that.
        any_live_update = any(flags.live_update_active
                              for flags in stage_flags)

        # The user isn't allowed to touch anything while batch processing is running.
        batch_processing_busy = self.batchProcessingApplet.busy

        self._shell.setAppletEnabled(
            self.dataSelectionApplet, not any_live_update
            and not batch_processing_busy)

        for stage_index, (featureSelectionApplet, pcApplet) in enumerate(
                zip(self.featureSelectionApplets, self.pcApplets)):
            upstream_live_update = any(flags.live_update_active
                                       for flags in stage_flags[:stage_index])
            this_stage_live_update = stage_flags[
                stage_index].live_update_active
            downstream_live_update = any(flags.live_update_active
                                         for flags in stage_flags[stage_index +
                                                                  1:])

            self._shell.setAppletEnabled(
                featureSelectionApplet,
                stage_flags[stage_index].input_ready
                and not this_stage_live_update and not downstream_live_update
                and not batch_processing_busy,
            )

            self._shell.setAppletEnabled(
                pcApplet,
                stage_flags[stage_index].features_ready
                # and not downstream_live_update \ # Not necessary because live update modes are synced -- labels can't be added in live update.
                and not batch_processing_busy,
            )

        self._shell.setAppletEnabled(
            self.dataExportApplet, stage_flags[-1].predictions_ready
            and not batch_processing_busy)
        self._shell.setAppletEnabled(
            self.batchProcessingApplet, predictions_ready
            and not batch_processing_busy)

        # Lastly, check for certain "busy" conditions, during which we
        #  should prevent the shell from closing the project.
        busy = False
        busy |= self.dataSelectionApplet.busy
        busy |= any(applet.busy for applet in self.featureSelectionApplets)
        busy |= self.dataExportApplet.busy
        busy |= self.batchProcessingApplet.busy
        self._shell.enableProjectChanges(not busy)