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, 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()
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()
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)
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.
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()
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 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()
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