def run_export(self):
        """
        Request the volume in slices (running in parallel), and write each slice to the correct page.
        Note: We can't use BigRequestStreamer here, because the data for each slice wouldn't be 
              guaranteed to arrive in the correct order.
        """
        # Make the directory first if necessary
        export_dir = os.path.split(self.FilepathPattern.value)[0]
        if not os.path.exists(export_dir):
            os.makedirs(export_dir)

        # Blockshape is the same as the input shape, except for the sliced dimension
        step_axis = self._volume_axes[0]
        tagged_blockshape = self.Input.meta.getTaggedShape()
        tagged_blockshape[step_axis] = 1
        block_shape = (tagged_blockshape.values())
        logger.debug("Starting Multipage Sequence Export with block shape: {}".format( block_shape ))

        # Block step is all zeros except step axis, e.g. (0, 1, 0, 0, 0)
        block_step = numpy.array( self.Input.meta.getAxisKeys() ) == step_axis
        block_step = block_step.astype(int)

        filepattern = self.FilepathPattern.value

        # If the user didn't provide custom formatting for the slice field,
        #  auto-format to include zero-padding
        if '{slice_index}' in filepattern:
            filepattern = filepattern.format( slice_index='{' + 'slice_index:0{}'.format(self._max_slice_digits) + '}' )        

        self.progressSignal(0)
        # Nothing fancy here: Just loop over the blocks in order.
        tagged_shape = self.Input.meta.getTaggedShape()
        for block_index in xrange( tagged_shape[step_axis] ):
            roi = numpy.array(roiFromShape(block_shape))
            roi += block_index*block_step
            roi = map(tuple, roi)

            try:
                opSubregion = OpSubRegion( parent=self )
                opSubregion.Roi.setValue( roi )
                opSubregion.Input.connect( self.Input )

                formatted_path = filepattern.format( slice_index=(block_index + self.SliceIndexOffset.value) )
                opExportBlock = OpExportMultipageTiff( parent=self )
                opExportBlock.Input.connect( opSubregion.Output )
                opExportBlock.Filepath.setValue( formatted_path )

                block_start_progress = 100*block_index // tagged_shape[step_axis]
                def _handleBlockProgress(block_progress):
                    self.progressSignal( block_start_progress + block_progress//tagged_shape[step_axis] )
                opExportBlock.progressSignal.subscribe( _handleBlockProgress )

                # Run the export for this block
                opExportBlock.run_export()
            finally:
                opExportBlock.cleanUp()
                opSubregion.cleanUp()

        self.progressSignal(100)
Пример #2
0
 def testOutput(self):
     graph = Graph()
     data = numpy.random.random( (1,100,100,10,1) )
     opProvider = OpArrayPiper(graph=graph)
     opProvider.Input.setValue(data)
     
     opSubRegion = OpSubRegion( graph=graph )
     opSubRegion.Input.connect( opProvider.Output )
     
     opSubRegion.Roi.setValue( ((0,20,30,5,0), (1,30,50,8,1)) )
     
     subData = opSubRegion.Output( start=( 0,5,10,1,0 ), stop=( 1,10,20,3,1 ) ).wait()
     assert (subData == data[0:1, 25:30, 40:50, 6:8, 0:1]).all()
Пример #3
0
    def __init__(self, pos: QRect, inputSlot, editor=None, scene=None, parent=None, qcolor=QColor(0, 0, 255)):
        """
        Couples the functionality of the lazyflow operator OpSubRegion which gets a subregion of interest
        and the functionality of the resizable rectangle Item.
        Keeps the two functionality separated


        :param pos: initial position
        :param inputSlot: Should be the output slot of another operator from which you would like monitor a subregion
        :param scene: the scene where to put the graphics item
        :param parent: the parent object if any
        :param qcolor: initial color of the rectangle
        """
        assert inputSlot.meta.getTaggedShape()["c"] == 1

        assert parent is None, "FIXME: QT structure does not seem to be implemented thoroughly. parent is always None!"
        self._rectItem = QGraphicsResizableRect(pos.x(), pos.y(), pos.height(), pos.width(), scene, parent, editor)
        # self._rectItem.color=qcolor  # FIXME: color can't be set

        # sub region corresponding to the rectangle region
        self._opsub = OpSubRegion(graph=inputSlot.operator.graph, parent=inputSlot.operator.parent)

        self._inputSlot = inputSlot  # input slot which connect to the sub array

        self.boxLabel = None  # a reference to the label in the labellist model
        self._initConnect()
Пример #4
0
    def testDirtyPropagation_masked(self):
        graph = Graph()
        data = numpy.random.random( (1,100,100,10,1) )
        data = numpy.ma.masked_array(data, mask=numpy.ma.getmaskarray(data), fill_value=data.dtype.type(numpy.nan), shrink=False)
        data[:, 25] = numpy.ma.masked
        opProvider = OpArrayPiper(graph=graph)
        opProvider.Input.setValue(data)

        opSubRegion = OpSubRegion( graph=graph )
        opSubRegion.Input.connect( opProvider.Output )

        opSubRegion.Roi.setValue( ((0,20,30,5,0), (1,30,50,8,1)) )

        gotDirtyRois = []
        def handleDirty(slot, roi):
            gotDirtyRois.append(roi)
        opSubRegion.Output.notifyDirty(handleDirty)

        # Set an input dirty region that overlaps with the subregion
        key = numpy.s_[0:1, 15:35, 32:33, 0:10, 0:1 ]
        opProvider.Input.setDirty( key )

        assert len(gotDirtyRois) == 1
        assert gotDirtyRois[0].start == [0,0,2,0,0]
        assert gotDirtyRois[0].stop == [1,10,3,3,1]

        # Now mark a region that DOESN'T overlap with the subregion
        key = numpy.s_[0:1, 70:80, 32:33, 0:10, 0:1 ]
        opProvider.Input.setDirty( key )

        # Should have gotten no extra dirty notifications
        assert len(gotDirtyRois) == 1
    def __init__(self,
                 x,
                 y,
                 h,
                 w,
                 inputSlot,
                 scene=None,
                 parent=None,
                 qcolor=QColor(0, 0, 255)):
        '''
        Couples the functionality of the lazyflow operator OpSubRegion which gets a subregion of interest
        and the functionality of the resizable rectangle Item.
        Keeps the two functionality separated
        
        
        :param x: initial position scene coordinates
        :param y: initial position scene coordinates
        :param h: initial height
        :param w: initial width
        :param inputSlot: Should be the output slot of another operator from which you would like monitor a subregion
        :param scene: the scene where to put the graphics item
        :param parent: the parent object if any
        :param qcolor: initial color of the rectangle
        '''

        self._rectItem = QGraphicsResizableRect(x, y, h, w, scene, parent)
        self._opsub = OpSubRegion(
            graph=inputSlot.operator.graph, parent=inputSlot.operator.parent
        )  #sub region correspondig to the rectangle region
        #self.opsum = OpSumAll(graph=inputSlot.operator.graph)
        self._graph = inputSlot.operator.graph
        self._inputSlot = inputSlot  #input slot which connect to the sub array

        self.boxLabel = None  #a reference to the label in the labellist model
        self._initConnect()
Пример #6
0
def get_model_op(wrappedOp):
    """
    Create a "model operator" that the gui can use.  
    The model op is a single (non-wrapped) export operator that the 
    gui will manipulate while the user plays around with the export 
    settings.  When the user is finished, the model op slot settings can 
    be copied over to the 'real' (wrapped) operator slots. 
    """
    if len(wrappedOp) == 0:
        return None, None

    # These are the slots the export settings gui will manipulate.
    setting_slots = [
        wrappedOp.RegionStart, wrappedOp.RegionStop, wrappedOp.InputMin,
        wrappedOp.InputMax, wrappedOp.ExportMin, wrappedOp.ExportMax,
        wrappedOp.ExportDtype, wrappedOp.OutputAxisOrder,
        wrappedOp.OutputFilenameFormat, wrappedOp.OutputInternalPath,
        wrappedOp.OutputFormat
    ]

    # Use an instance of OpFormattedDataExport, since has the important slots and no others.
    model_op = OpFormattedDataExport(parent=wrappedOp.parent)
    for slot in setting_slots:
        model_inslot = getattr(model_op, slot.name)
        if slot.ready():
            model_inslot.setValue(slot.value)

    # Choose a roi that can apply to all images in the original operator
    shape = None
    axes = None
    for multislot in wrappedOp.Inputs:
        slot = multislot[wrappedOp.InputSelection.value]
        if slot.ready():
            if shape is None:
                shape = slot.meta.shape
                axes = slot.meta.getAxisKeys()
                dtype = slot.meta.dtype
            else:
                assert slot.meta.getAxisKeys(
                ) == axes, "Can't export multiple slots with different axes."
                assert slot.meta.dtype == dtype
                shape = numpy.minimum(slot.meta.shape, shape)

    # If NO slots were ready, then we can't do anything here.
    if shape is None:
        return None, None

    # Must provide a 'ready' slot for the gui
    # Use a subregion operator to provide a slot with the meta data we chose.
    opSubRegion = OpSubRegion(parent=wrappedOp.parent)
    opSubRegion.Roi.setValue([(0, ) * len(shape), tuple(shape)])
    opSubRegion.Input.connect(slot)

    # (The actual contents of this slot are not important to the settings gui.
    #  It only cares about the metadata.)
    model_op.Input.connect(opSubRegion.Output)

    return model_op, opSubRegion  # We return the subregion op, too, so the caller can clean it up.
Пример #7
0
    def testOutput_masked(self):
        graph = Graph()
        data = numpy.random.random( (1,100,100,10,1) )
        data = numpy.ma.masked_array(data,
                                     mask=numpy.ma.getmaskarray(data),
                                     fill_value=data.dtype.type(numpy.nan),
                                     shrink=False
        )
        data[:, 25] = numpy.ma.masked
        opProvider = OpArrayPiper(graph=graph)
        opProvider.Input.setValue(data)

        opSubRegion = OpSubRegion( graph=graph )
        opSubRegion.Input.connect( opProvider.Output )

        opSubRegion.Roi.setValue( ((0,20,30,5,0), (1,30,50,8,1)) )

        subData = opSubRegion.Output( start=( 0,5,10,1,0 ), stop=( 1,10,20,3,1 ) ).wait()
        assert (subData == data[0:1, 25:30, 40:50, 6:8, 0:1]).all()
        assert (subData.mask == data.mask[0:1, 25:30, 40:50, 6:8, 0:1]).all()
        assert ((subData.fill_value == data.fill_value) |
                (numpy.isnan(subData.fill_value) & numpy.isnan(data.fill_value))).all()
Пример #8
0
    def getFeatureLayers(self, inputSlot, featureSlot):
        """
        Generate a list of layers for the feature image produced by the given slot.
        """
        layers = []

        channelAxis = inputSlot.meta.axistags.channelIndex
        assert channelAxis == featureSlot.meta.axistags.channelIndex
        numInputChannels = inputSlot.meta.shape[channelAxis]
        numFeatureChannels = featureSlot.meta.shape[channelAxis]

        # Determine how many channels this feature has (up to 3)
        featureChannelsPerInputChannel = numFeatureChannels // numInputChannels
        if not 0 < featureChannelsPerInputChannel <= 3:
            logger.warning(
                "The feature selection Gui does not yet support features with more than three channels per "
                "input channel. Some features will not be displayed entirely.")

        for inputChannel in range(numInputChannels):
            # Determine the name for this feature
            featureName = featureSlot.meta.description
            assert featureName is not None
            if 2 <= numInputChannels <= 3:
                channelNames = ["R", "G", "B"]
                featureName += " (" + channelNames[inputChannel] + ")"
            if numInputChannels > 3:
                featureName += " (Ch. {})".format(inputChannel)

            opSubRegion = OpSubRegion(parent=self.topLevelOperatorView.parent)
            opSubRegion.Input.connect(featureSlot)
            start = [0] * len(featureSlot.meta.shape)
            start[channelAxis] = inputChannel * featureChannelsPerInputChannel
            stop = list(featureSlot.meta.shape)
            stop[channelAxis] = (inputChannel +
                                 1) * featureChannelsPerInputChannel

            opSubRegion.Roi.setValue((tuple(start), tuple(stop)))

            featureLayer = self.createStandardLayerFromSlot(opSubRegion.Output)
            featureLayer.visible = False
            featureLayer.opacity = 1.0
            featureLayer.name = featureName

            layers.append(featureLayer)

        return layers
    def __init__(self, *args, **kwargs):
        super(OpFormattedDataExport, self).__init__(*args, **kwargs)
        self._dirty = True

        opSubRegion = OpSubRegion(parent=self)
        opSubRegion.Input.connect(self.Input)
        self._opSubRegion = opSubRegion

        # If normalization parameters are provided, we inject a 'drange'
        #  metadata item for downstream operators/gui to use.
        opDrangeInjection = OpMetadataInjector(parent=self)
        opDrangeInjection.Input.connect(opSubRegion.Output)
        self._opDrangeInjection = opDrangeInjection

        # Normalization and dtype conversion are performed in one step
        #  using an OpPixelOperator.
        opNormalizeAndConvert = OpPixelOperator(parent=self)
        opNormalizeAndConvert.Input.connect(opDrangeInjection.Output)
        self._opNormalizeAndConvert = opNormalizeAndConvert

        # ConvertedImage shows the full result but WITHOUT axis reordering.
        self.ConvertedImage.connect(self._opNormalizeAndConvert.Output)

        opReorderAxes = OpReorderAxes(parent=self)
        opReorderAxes.Input.connect(opNormalizeAndConvert.Output)
        self._opReorderAxes = opReorderAxes

        self.ImageToExport.connect(opReorderAxes.Output)

        self._opExportSlot = OpExportSlot(parent=self)
        self._opExportSlot.Input.connect(opReorderAxes.Output)
        self._opExportSlot.OutputFormat.connect(self.OutputFormat)

        self.ExportPath.connect(self._opExportSlot.ExportPath)
        self.FormatSelectionErrorMsg.connect(
            self._opExportSlot.FormatSelectionErrorMsg)
        self.progressSignal = self._opExportSlot.progressSignal