def __init__(self, *args, **kwargs): super(OpPredictionPipeline, self).__init__(*args, **kwargs) self.cacheless_predict = OpTikTorchClassifierPredict(parent=self) self.cacheless_predict.name = "OpTiktorchClassifierPredict (Cacheless Path)" self.cacheless_predict.ModelSession.connect(self.Classifier) self.cacheless_predict.Image.connect( self.RawImage) # <--- Not from cache self.cacheless_predict.LabelsCount.connect(self.NumClasses) self.predict = OpTikTorchClassifierPredict(parent=self) self.predict.name = "OpTiktorchClassifierPredict" self.predict.ModelSession.connect(self.Classifier) self.predict.Image.connect(self.RawImage) self.predict.LabelsCount.connect(self.NumClasses) self.predict.BlockShape.connect(self.BlockShape) self.splitReqests = OpBlockedArrayCache(parent=self) self.splitReqests.Input.connect(self.predict.PMaps) self.splitReqests.BlockShape.connect(self.predict.BlockShape) self.PredictionProbabilities.connect(self.splitReqests.Output) self.prediction_cache = OpBlockedArrayCache(parent=self) self.prediction_cache.name = "BlockedArrayCache" self.prediction_cache.fixAtCurrent.connect(self.FreezePredictions) self.prediction_cache.BlockShape.connect(self.BlockShape) self.prediction_cache.Input.connect(self.predict.PMaps) self.CachedPredictionProbabilities.connect( self.prediction_cache.Output) self.opPredictionSlicer = OpMultiArraySlicer2(parent=self) self.opPredictionSlicer.name = "opPredictionSlicer" self.opPredictionSlicer.Input.connect(self.prediction_cache.Output) self.opPredictionSlicer.AxisFlag.setValue("c") self.PredictionProbabilityChannels.connect( self.opPredictionSlicer.Slices)
def testCleanup(self): try: ArrayCacheMemoryMgr.instance.pause() op = OpBlockedArrayCache(graph=self.opProvider.graph) op.Input.connect(self.opProvider.Output) s = self.opProvider.Output.meta.shape op.innerBlockShape.setValue(s) op.outerBlockShape.setValue(s) op.fixAtCurrent.setValue(False) x = op.Output[...].wait() op.Input.disconnect() op.cleanUp() r = weakref.ref(op) del op gc.collect() ref = r() if ref is not None: for i, o in enumerate(gc.get_referrers(ref)): print "Object", i, ":", type(o), ":", o assert r( ) is None, "OpBlockedArrayCache was not cleaned up correctly" finally: ArrayCacheMemoryMgr.instance.unpause()
def __init__(self, *args, **kwargs): super(OpSlicCached, self).__init__(*args, **kwargs) # This operator does no computation on its own. # Instead, it owns a little internal pipeline: # # Input --> OpSlic --> OpCache --> Output # # Feed all inputs directly into the operator that actually computes the slic superpixels self.opSlic = OpSlic(parent=self) self.opSlic.NumSegments.connect(self.NumSegments) self.opSlic.Compactness.connect(self.Compactness) self.opSlic.MaxIter.connect(self.MaxIter) self.opSlic.Input.connect(self.Input) self.opCache = OpBlockedArrayCache(parent=self) self.opCache.Input.connect(self.opSlic.Output) self.Output.connect(self.opCache.Output) self.CleanBlocks.connect(self.opCache.CleanBlocks) self.opSlicBoundaries = OpSlicBoundariesCached(parent=self) self.opSlicBoundaries.SegmentationInput.connect(self.opCache.Output) self.opBoundariesCache = OpBlockedArrayCache(parent=self) self.opBoundariesCache.Input.connect( self.opSlicBoundaries.BoundariesOutput) self.BoundariesOutput.connect(self.opBoundariesCache.Output) self.BoundariesCleanBlocks.connect(self.opBoundariesCache.CleanBlocks)
def __init__(self, *args, **kwargs): super(OpPreprocessing, self).__init__(*args, **kwargs) self._prepData = [None] self.applet = self.parent.parent.preprocessingApplet self._unsavedData = False # set to True if data is not yet saved self._dirty = False # set to True if any Input is dirty self.initialSigma = None # save settings of last preprocess self.initialFilter = None # applied to gui by pressing reset self.initialDoAgglo = None self.initialSizeRegularizer = None self.initialReduceTo = None self._opFilter = OpFilter(parent=self) self._opFilter.Input.connect(self.InputData) self._opFilter.Sigma.connect(self.Sigma) self._opFilter.Filter.connect(self.Filter) self._opFilterNormalize = OpNormalize255(parent=self) self._opFilterNormalize.Input.connect(self._opFilter.Output) self._opFilterCache = OpBlockedArrayCache(parent=self) self._opWatershed = OpSimpleBlockwiseWatershed(parent=self) self._opWatershed.DoAgglo.connect(self.SizeRegularizer) self._opWatershed.ReduceTo.connect(self.ReduceTo) self._opWatershed.SizeRegularizer.connect(self.SizeRegularizer) self._opWatershedCache = OpBlockedArrayCache(parent=self) self._opOverlayFilter = OpFilter(parent=self) self._opOverlayFilter.Input.connect(self.OverlayData) self._opOverlayFilter.Sigma.connect(self.Sigma) self._opOverlayNormalize = OpNormalize255(parent=self) self._opOverlayNormalize.Input.connect(self._opOverlayFilter.Output) self._opInputFilter = OpFilter(parent=self) self._opInputFilter.Input.connect(self.InputData) self._opInputFilter.Sigma.connect(self.Sigma) self._opInputNormalize = OpNormalize255(parent=self) self._opInputNormalize.Input.connect(self._opInputFilter.Output) self._opMstProvider = OpMstSegmentorProvider(self.applet, parent=self) self._opMstProvider.Image.connect(self._opFilterCache.Output) self._opMstProvider.LabelImage.connect(self._opWatershedCache.Output) self._opWatershedSourceCache = OpBlockedArrayCache(parent=self) #self.PreprocessedData.connect( self._opMstProvider.MST ) # Display slots self.FilteredImage.connect(self._opFilterCache.Output) self.WatershedImage.connect(self._opWatershedCache.Output) self.InputData.notifyReady(self._checkConstraints)
def __init__(self, *args, **kwargs): super(OpMulticut, self).__init__(*args, **kwargs) self.opMulticutAgglomerator = OpMulticutAgglomerator(parent=self) self.opMulticutAgglomerator.Beta.connect(self.Beta) self.opMulticutAgglomerator.SolverName.connect(self.SolverName) self.opMulticutAgglomerator.Rag.connect(self.Rag) self.opMulticutAgglomerator.EdgeProbabilities.connect( self.EdgeProbabilities) self.opNodeLabelsCache = OpValueCache(parent=self) self.opNodeLabelsCache.fixAtCurrent.connect(self.FreezeCache) self.opNodeLabelsCache.Input.connect( self.opMulticutAgglomerator.NodeLabels) self.opNodeLabelsCache.name = 'opNodeLabelCache' self.opRelabel = OpProjectNodeLabeling(parent=self) self.opRelabel.Superpixels.connect(self.Superpixels) self.opRelabel.NodeLabels.connect(self.opNodeLabelsCache.Output) self.opDisagreement = OpEdgeLabelDisagreementDict(parent=self) self.opDisagreement.Rag.connect(self.Rag) self.opDisagreement.NodeLabels.connect(self.opNodeLabelsCache.Output) self.opDisagreement.EdgeProbabilities.connect(self.EdgeProbabilities) self.EdgeLabelDisagreementDict.connect( self.opDisagreement.EdgeLabelDisagreementDict) self.opSegmentationCache = OpBlockedArrayCache(parent=self) self.opSegmentationCache.fixAtCurrent.connect(self.FreezeCache) self.opSegmentationCache.Input.connect(self.opRelabel.Output) self.Output.connect(self.opSegmentationCache.Output)
def test_basic(self): graph = lazyflow.graph.Graph() data = numpy.indices((100, 100), dtype=numpy.uint8).sum(0) data = vigra.taggedView(data, vigra.defaultAxistags("xy")) opDataProvider = OpBlockedArrayCache(graph=graph) opDataProvider.Input.setValue(data) op = OpZeroDefault(graph=graph) op.MetaInput.setValue(data) # Zero by default output_data = op.Output[:].wait() assert (output_data == 0).all() # Connecting a real input triggers dirty notification dirty_notification_count = [0] def handleDirty(*args): dirty_notification_count[0] += 1 op.Output.notifyDirty(handleDirty) op.Input.connect(opDataProvider.Output) assert dirty_notification_count[0] == 1 # Output should provide real data if available assert (op.Output[:].wait() == data.view(numpy.ndarray)).all() # Output provides zeros again when the data is no longer available op.Input.disconnect() output_data = op.Output[:].wait() assert (output_data == 0).all()
def __init__(self, *args, **kwargs): super(OpBatchIoSelective, self).__init__(*args, **kwargs) self.Dirty.meta.shape = (1, ) self.Dirty.meta.dtype = bool self.OutputDataPath.meta.shape = (1, ) self.OutputDataPath.meta.dtype = object self.ExportResult.meta.shape = (1, ) self.ExportResult.meta.dtype = object # Provide default values self.ExportDirectory.setValue('') self.Format.setValue(ExportFormat.H5) self.Suffix.setValue('_results') self.Dirty.setValue(True) self.progressSignal = OrderedSignal() self.ProgressSignal.setValue(self.progressSignal) self._createDirLock = threading.Lock() #make a cache of the input image not to request too much self.ImageCache = OpBlockedArrayCache(parent=self) self.ImageCache.fixAtCurrent.setValue(False) self.ImageCache.Input.connect(self.ImageToExport)
def testBasic_2d_Sequence(self): data = 255 * numpy.random.random((10, 50, 100, 3)) data = data.astype(numpy.uint8) data = vigra.taggedView(data, vigra.defaultAxistags("zyxc")) # Must run this through an operator # Can't use opExport.setValue() because because OpStackWriter can't work with ValueRequests graph = Graph() opData = OpBlockedArrayCache(graph=graph) opData.BlockShape.setValue(data.shape) opData.Input.setValue(data) filepattern = self._tmpdir + "/test_export_x{x_start}-{x_stop}_y{y_start}-{y_stop}_z{slice_index}" opExport = OpExportSlot(graph=graph) opExport.Input.connect(opData.Output) opExport.OutputFormat.setValue("png sequence") opExport.OutputFilenameFormat.setValue(filepattern) opExport.CoordinateOffset.setValue((10, 20, 30, 0)) opExport.run_export() export_pattern = opExport.ExportPath.value globstring = export_pattern.format(slice_index=999) globstring = globstring.replace("999", "*") opReader = OpStackLoader(graph=graph) try: opReader.globstring.setValue(globstring) assert opReader.stack.meta.shape == data.shape, "Exported files were of the wrong shape or number." assert (opReader.stack[:].wait() == data.view(numpy.ndarray)).all(), "Exported data was not correct" finally: opReader.cleanUp()
def _attemptOpenWithVigraImpex(self, filePath): fileExtension = os.path.splitext(filePath)[1].lower() fileExtension = fileExtension.lstrip('.') # Remove leading dot if fileExtension not in OpInputDataReader.vigraImpexExts: return ([], None) if not os.path.exists(filePath): raise OpInputDataReader.DatasetReadError( "Input file does not exist: " + filePath) vigraReader = OpImageReader(parent=self) vigraReader.Filename.setValue(filePath) # Cache the image instead of reading the hard disk for every access. imageCache = OpBlockedArrayCache(parent=self) imageCache.Input.connect(vigraReader.Image) # 2D: Just one block for the whole image cacheBlockShape = vigraReader.Image.meta.shape taggedShape = vigraReader.Image.meta.getTaggedShape() if 'z' in taggedShape.keys(): # 3D: blocksize is one slice. taggedShape['z'] = 1 cacheBlockShape = tuple(taggedShape.values()) imageCache.fixAtCurrent.setValue(False) imageCache.innerBlockShape.setValue(cacheBlockShape) imageCache.outerBlockShape.setValue(cacheBlockShape) assert imageCache.Output.ready() return ([vigraReader, imageCache], imageCache.Output)
def __init__(self, *args, **kwargs): super(OpCachedWsdt, self).__init__(*args, **kwargs) my_slot_names = set( map(lambda slot: slot.name, self.inputSlots + self.outputSlots)) wsdt_slot_names = set( map(lambda slot: slot.name, OpWsdt.inputSlots + OpWsdt.outputSlots)) assert wsdt_slot_names.issubset(my_slot_names), \ "OpCachedWsdt should have all of the slots that OpWsdt has (and maybe more). "\ "Did you add a slot to OpWsdt and forget to add it to OpCachedWsdt?" self._opWsdt = OpWsdt(parent=self) self._opWsdt.Input.connect(self.Input) self._opWsdt.ChannelSelection.connect(self.ChannelSelection) self._opWsdt.Pmin.connect(self.Pmin) self._opWsdt.MinMembraneSize.connect(self.MinMembraneSize) self._opWsdt.MinSegmentSize.connect(self.MinSegmentSize) self._opWsdt.SigmaMinima.connect(self.SigmaMinima) self._opWsdt.SigmaWeights.connect(self.SigmaWeights) self._opWsdt.GroupSeeds.connect(self.GroupSeeds) self._opWsdt.EnableDebugOutputs.connect(self.EnableDebugOutputs) self._opCache = OpBlockedArrayCache(parent=self) self._opCache.fixAtCurrent.connect(self.FreezeCache) self._opCache.Input.connect(self._opWsdt.Superpixels) self.Superpixels.connect(self._opCache.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks) self._opSelectedInput = OpSingleChannelSelector(parent=self) self._opSelectedInput.Index.connect(self.ChannelSelection) self._opSelectedInput.Input.connect(self.Input) self._opThreshold = OpPixelOperator(parent=self) self._opThreshold.Input.connect(self._opSelectedInput.Output) self.ThresholdedInput.connect(self._opThreshold.Output)
def test_Writer(self): opData = OpBlockedArrayCache(graph=self.graph) opData.BlockShape.setValue(self.testData.shape) opData.Input.setValue(self.testData) opWriter = OpStackWriter(graph=self.graph) opWriter.FilepathPattern.setValue(self._stack_filepattern) opWriter.Input.connect(opData.Output) # opWriter.Input.setValue( self.testData ) opWriter.SliceIndexOffset.setValue(22) # Run the export opWriter.run_export() globstring = self._stack_filepattern.format(slice_index=999) globstring = globstring.replace("999", "*") opReader = OpStackLoader(graph=self.graph) opReader.globstring.setValue(globstring) # (The OpStackLoader might produce different order.) opReorderAxes = OpReorderAxes(graph=self.graph) opReorderAxes.AxisOrder.setValue(self._axisorder) opReorderAxes.Input.connect(opReader.stack) readData = opReorderAxes.Output[:].wait() logger.debug("Expected shape={}".format(self.testData.shape)) logger.debug("Read shape={}".format(readData.shape)) assert (opReorderAxes.Output.meta.shape == self.testData.shape ), "Exported files were of the wrong shape or number." assert (opReorderAxes.Output[:].wait() == self.testData.view( numpy.ndarray)).all(), "Exported data was not correct"
def __init__(self, block_roi, halo_padding, *args, **kwargs): super( self.__class__, self ).__init__( *args, **kwargs ) self.block_roi = block_roi # In global coordinates self._halo_padding = halo_padding self._opBinarySubRegion = OpSubRegion( parent=self ) self._opBinarySubRegion.Input.connect( self.BinaryImage ) self._opRawSubRegion = OpSubRegion( parent=self ) self._opRawSubRegion.Input.connect( self.RawImage ) self._opExtract = OpObjectExtraction( parent=self ) self._opExtract.BinaryImage.connect( self._opBinarySubRegion.Output ) self._opExtract.RawImage.connect( self._opRawSubRegion.Output ) self._opExtract.Features.connect(self.SelectedFeatures) self.BlockwiseRegionFeatures.connect( self._opExtract.BlockwiseRegionFeatures ) self._opExtract._opRegFeats._opCache.name = "blockwise-regionfeats-cache" self._opPredict = OpObjectPredict( parent=self ) self._opPredict.Features.connect( self._opExtract.RegionFeatures ) self._opPredict.SelectedFeatures.connect( self.SelectedFeatures ) self._opPredict.Classifier.connect( self.Classifier ) self._opPredict.LabelsCount.connect( self.LabelsCount ) self.ObjectwisePredictions.connect( self._opPredict.Predictions ) self._opPredictionImage = OpRelabelSegmentation( parent=self ) self._opPredictionImage.Image.connect( self._opExtract.LabelImage ) self._opPredictionImage.Features.connect( self._opExtract.RegionFeatures ) self._opPredictionImage.ObjectMap.connect( self._opPredict.Predictions ) self._opPredictionCache = OpBlockedArrayCache( parent=self ) self._opPredictionCache.Input.connect( self._opPredictionImage.Output ) self._opProbabilityChannelsToImage = OpMultiRelabelSegmentation( parent=self ) self._opProbabilityChannelsToImage.Image.connect( self._opExtract.LabelImage ) self._opProbabilityChannelsToImage.ObjectMaps.connect( self._opPredict.ProbabilityChannels ) self._opProbabilityChannelsToImage.Features.connect( self._opExtract.RegionFeatures ) self._opProbabilityChannelStacker = OpMultiArrayStacker( parent=self ) self._opProbabilityChannelStacker.Images.connect( self._opProbabilityChannelsToImage.Output ) self._opProbabilityChannelStacker.AxisFlag.setValue('c') self._opProbabilityCache = OpBlockedArrayCache( parent=self ) self._opProbabilityCache.Input.connect( self._opProbabilityChannelStacker.Output )
def __init__(self, *args, **kwargs): super(OpLabelingABC, self).__init__(*args, **kwargs) self._cache = OpBlockedArrayCache(parent=self) self._cache.name = "OpLabelVolume.OutputCache" self._cache.CompressionEnabled.setValue(True) self._cache.Input.connect(self.Output) self.CachedOutput.connect(self._cache.Output) self.CleanBlocks.connect(self._cache.CleanBlocks)
def __init__(self, *args, **kwargs): super(OpLabelingABC, self).__init__(*args, **kwargs) self._cache = OpBlockedArrayCache(parent=self) self._cache.name = "OpLabelVolume.OutputCache" self._cache.BypassModeEnabled.connect(self.BypassModeEnabled) self._cache.Input.connect(self.Output) self.CachedOutput.connect(self._cache.Output) self.CleanBlocks.connect(self._cache.CleanBlocks)
def __init__(self, parent=None, graph=None): super(OpConservationTracking, self).__init__(parent=parent, graph=graph) self._opCache = OpBlockedArrayCache(parent=self) self._opCache.name = "OpConservationTracking._opCache" self._opCache.Input.connect(self.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks) self.CachedOutput.connect(self._opCache.Output) self.zeroProvider = OpZeroDefault(parent=self) self.zeroProvider.MetaInput.connect(self.LabelImage) # As soon as input data is available, check its constraints self.RawImage.notifyReady(self._checkConstraints) self.LabelImage.notifyReady(self._checkConstraints) self.ExportSettings.setValue((None, None)) self._mergerOpCache = OpBlockedArrayCache(parent=self) self._mergerOpCache.name = "OpConservationTracking._mergerOpCache" self._mergerOpCache.Input.connect(self.MergerOutput) self.MergerCleanBlocks.connect(self._mergerOpCache.CleanBlocks) self.MergerCachedOutput.connect(self._mergerOpCache.Output) self._relabeledOpCache = OpBlockedArrayCache(parent=self) self._relabeledOpCache.name = "OpConservationTracking._mergerOpCache" self._relabeledOpCache.Input.connect(self.RelabeledImage) self.RelabeledCleanBlocks.connect(self._relabeledOpCache.CleanBlocks) self.RelabeledCachedOutput.connect(self._relabeledOpCache.Output) # Merger resolver plugin manager (contains GMM fit routine) self.pluginPaths = [ os.path.join(os.path.dirname(os.path.abspath(hytra.__file__)), 'plugins') ] pluginManager = TrackingPluginManager(verbose=False, pluginPaths=self.pluginPaths) self.mergerResolverPlugin = pluginManager.getMergerResolver() self.result = None # progress bar self.progressWindow = None self.progressVisitor = DefaultProgressVisitor()
def __init__(self, *args, **kwargs): super(OpPredictionPipeline, self).__init__(*args, **kwargs) # Random forest prediction using CACHED features. self.predict = OpPredictCounter(parent=self) self.predict.name = "OpPredictCounter" self.predict.inputs["Classifier"].connect(self.Classifier) self.predict.inputs["Image"].connect(self.CachedFeatureImages) self.predict.inputs["LabelsCount"].connect(self.MaxLabel) self.PredictionProbabilities.connect(self.predict.PMaps) # Prediction cache for the GUI self.prediction_cache_gui = OpBlockedArrayCache(parent=self) self.prediction_cache_gui.name = "prediction_cache_gui" self.prediction_cache_gui.inputs["fixAtCurrent"].connect( self.FreezePredictions) self.prediction_cache_gui.inputs["Input"].connect(self.predict.PMaps) self.prediction_cache_gui.BlockShape.setValue((128, 128, None)) ## Also provide each prediction channel as a separate layer (for the GUI) self.opUncertaintyEstimator = OpEnsembleMargin(parent=self) self.opUncertaintyEstimator.Input.connect( self.prediction_cache_gui.Output) ## Cache the uncertainty so we get zeros for uncomputed points self.opUncertaintyCache = OpBlockedArrayCache(parent=self) self.opUncertaintyCache.name = "opUncertaintyCache" self.opUncertaintyCache.BlockShape.setValue((128, 128, None)) self.opUncertaintyCache.Input.connect( self.opUncertaintyEstimator.Output) self.opUncertaintyCache.fixAtCurrent.connect(self.FreezePredictions) self.UncertaintyEstimate.connect(self.opUncertaintyCache.Output) self.meaner = OpMean(parent=self) self.meaner.Input.connect(self.predict.PMaps) self.precomputed_predictions_gui = OpPrecomputedInput( ignore_dirty_input=False, parent=self) self.precomputed_predictions_gui.name = "precomputed_predictions_gui" self.precomputed_predictions_gui.SlowInput.connect(self.meaner.Output) self.precomputed_predictions_gui.PrecomputedInput.connect( self.PredictionsFromDisk) self.CachedPredictionProbabilities.connect( self.precomputed_predictions_gui.Output)
def __init__(self, *args, **kwargs): super(OpFillMissingSlices, self).__init__(*args, **kwargs) # The cache serves two purposes: # 1) Determine shape of accesses to the interpolation operator # 2) Avoid duplicating work self._opCache = OpBlockedArrayCache(parent=self) self._opCache.Input.connect(self._opInterp.Output) self._opCache.fixAtCurrent.setValue(False) self.CachedOutput.connect(self._opCache.Output)
def __init__(self, *args, **kwargs): super(OpMulticut, self).__init__(*args, **kwargs) self.opMulticutAgglomerator = OpMulticutAgglomerator(parent=self) self.opMulticutAgglomerator.Superpixels.connect(self.Superpixels) self.opMulticutAgglomerator.Beta.connect(self.Beta) self.opMulticutAgglomerator.SolverName.connect(self.SolverName) self.opMulticutAgglomerator.Rag.connect(self.Rag) self.opMulticutAgglomerator.EdgeProbabilities.connect( self.EdgeProbabilities) self.opSegmentationCache = OpBlockedArrayCache(parent=self) self.opSegmentationCache.fixAtCurrent.connect(self.FreezeCache) self.opSegmentationCache.Input.connect( self.opMulticutAgglomerator.Output) self.Output.connect(self.opSegmentationCache.Output)
def __init__(self, *args, **kwargs): super(OpCachedRegionFeatures, self).__init__(*args, **kwargs) # Hook up the actual region features operator self._opRegionFeatures = OpRegionFeatures(parent=self) self._opRegionFeatures.RawVolume.connect(self.RawImage) self._opRegionFeatures.LabelVolume.connect(self.LabelImage) self._opRegionFeatures.Features.connect(self.Features) # Hook up the cache. self._opCache = OpBlockedArrayCache(parent=self) self._opCache.name = "OpCachedRegionFeatures._opCache" self._opCache.Input.connect(self._opRegionFeatures.Output) # Hook up our output slots self.Output.connect(self._opCache.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks)
def setUp(self): self.dataShape = (1,100,100,10,1) self.data = (numpy.random.random(self.dataShape) * 100).astype(int) self.data = self.data.view(vigra.VigraArray) self.data.axistags = vigra.defaultAxistags('txyzc') graph = Graph() opProvider = OpArrayPiperWithAccessCount(graph=graph) opProvider.Input.setValue(self.data) self.opProvider = opProvider opCache = OpBlockedArrayCache(graph=graph) opCache.Input.connect(opProvider.Output) opCache.innerBlockShape.setValue( (10,10,10,10,10) ) opCache.outerBlockShape.setValue( (20,20,20,20,20) ) opCache.fixAtCurrent.setValue(False) self.opCache = opCache
def testBasic_MultipageTiffSequence(self): data = 255 * numpy.random.random((5, 10, 50, 100, 3)) data = data.astype(numpy.uint8) data = vigra.taggedView(data, vigra.defaultAxistags('tzyxc')) # Must run this through an operator # Can't use opExport.setValue() because because OpStackWriter can't work with ValueRequests graph = Graph() opData = OpBlockedArrayCache(graph=graph) opData.BlockShape.setValue(data.shape) opData.Input.setValue(data) filepattern = self._tmpdir + '/test_export_x{x_start}-{x_stop}_y{y_start}-{y_stop}_t{slice_index}' opExport = OpExportSlot(graph=graph) opExport.Input.connect(opData.Output) opExport.OutputFormat.setValue('multipage tiff sequence') opExport.OutputFilenameFormat.setValue(filepattern) opExport.CoordinateOffset.setValue((7, 10, 20, 30, 0)) opExport.run_export() export_pattern = opExport.ExportPath.value globstring = export_pattern.format(slice_index=999) globstring = globstring.replace('999', '*') opReader = OpTiffSequenceReader(graph=graph) opReorderAxes = OpReorderAxes(graph=graph) try: opReader.GlobString.setValue(globstring) # (The OpStackLoader produces txyzc order.) opReorderAxes.AxisOrder.setValue('tzyxc') opReorderAxes.Input.connect(opReader.Output) assert opReorderAxes.Output.meta.shape == data.shape, "Exported files were of the wrong shape or number." assert (opReorderAxes.Output[:].wait() == data.view( numpy.ndarray)).all(), "Exported data was not correct" finally: opReorderAxes.cleanUp() opReader.cleanUp()
def __init__(self, *args, **kwargs): super(OpCachedDivisionFeatures, self).__init__(*args, **kwargs) # Hook up the labeler self._opDivisionFeatures = OpDivisionFeatures(parent=self) self._opDivisionFeatures.LabelVolume.connect(self.LabelImage) self._opDivisionFeatures.DivisionFeatureNames.connect( self.DivisionFeatureNames) self._opDivisionFeatures.RegionFeaturesVigra.connect( self.RegionFeaturesVigra) # Hook up the cache. self._opCache = OpBlockedArrayCache(parent=self) self._opCache.name = "OpCachedDivisionFeatures._opCache" self._opCache.Input.connect( self._opDivisionFeatures.BlockwiseDivisionFeatures) # Hook up our output slots self.Output.connect(self._opCache.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks)
def __init__(self, *args, **kwargs): super(OpCachedWsdt, self).__init__(*args, **kwargs) my_slot_names = set( [slot.name for slot in self.inputSlots + self.outputSlots]) wsdt_slot_names = set( [slot.name for slot in OpWsdt.inputSlots + OpWsdt.outputSlots]) assert wsdt_slot_names.issubset(my_slot_names), ( "OpCachedWsdt should have all of the slots that OpWsdt has (and maybe more)." "Did you add a slot to OpWsdt and forget to add it to OpCachedWsdt?" ) self._opWsdt = OpWsdt(parent=self) self._opWsdt.Input.connect(self.Input) self._opWsdt.ChannelSelections.connect(self.ChannelSelections) self._opWsdt.Threshold.connect(self.Threshold) self._opWsdt.MinSize.connect(self.MinSize) self._opWsdt.Sigma.connect(self.Sigma) self._opWsdt.Alpha.connect(self.Alpha) self._opWsdt.PixelPitch.connect(self.PixelPitch) self._opWsdt.ApplyNonmaxSuppression.connect( self.ApplyNonmaxSuppression) self._opWsdt.InvertPixelProbabilities.connect( self.InvertPixelProbabilities) self._opWsdt.EnableDebugOutputs.connect(self.EnableDebugOutputs) self._opCache = OpBlockedArrayCache(parent=self) self._opCache.fixAtCurrent.connect(self.FreezeCache) self._opCache.Input.connect(self._opWsdt.Superpixels) self.Superpixels.connect(self._opCache.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks) self._opSelectedInput = OpSumChannels(parent=self) self._opSelectedInput.ChannelSelections.connect(self.ChannelSelections) self._opSelectedInput.Input.connect(self.Input) self._opSelectedInput.InvertPixelProbabilities.connect( self.InvertPixelProbabilities) self.SelectedInput.connect(self._opSelectedInput.Output) self._opThreshold = OpPixelOperator(parent=self) self._opThreshold.Input.connect(self._opSelectedInput.Output) self.ThresholdedInput.connect(self._opThreshold.Output)
def test_basic(self): opSource = OpArrayPiper(graph=self.graph) opSource.Input.setValue(self.testData) opData = OpBlockedArrayCache(graph=self.graph) opData.BlockShape.setValue(self.testData.shape) opData.Input.connect(opSource.Output) filepath = os.path.join(self._tmpdir, 'multipage.tiff') logger.debug("writing to: {}".format(filepath)) opExport = OpExportMultipageTiff(graph=self.graph) opExport.Filepath.setValue(filepath) opExport.Input.connect(opData.Output) # Run the export opExport.run_export() opReader = OpTiffReader(graph=self.graph) try: opReader.Filepath.setValue(filepath) # Re-order before comparing opReorderAxes = OpReorderAxes(graph=self.graph) try: opReorderAxes.AxisOrder.setValue(self._axisorder) opReorderAxes.Input.connect(opReader.Output) readData = opReorderAxes.Output[:].wait() logger.debug("Expected shape={}".format(self.testData.shape)) logger.debug("Read shape={}".format(readData.shape)) assert opReorderAxes.Output.meta.shape == self.testData.shape, \ "Exported files were of the wrong shape or number." assert (opReorderAxes.Output[:].wait() == self.testData.view( numpy.ndarray )).all(), \ "Exported data was not correct" finally: opReorderAxes.cleanUp() finally: opReader.cleanUp()
def _attemptOpenAsTiff(self, filePath): fileExtension = os.path.splitext(filePath)[1].lower() fileExtension = fileExtension.lstrip(".") # Remove leading dot if fileExtension not in OpInputDataReader.tiffExts: return ([], None) if not os.path.exists(filePath): raise OpInputDataReader.DatasetReadError("Input file does not exist: " + filePath) opReader = OpTiffReader(parent=self) opReader.Filepath.setValue(filePath) page_shape = opReader.Output.meta.ideal_blockshape # Cache the pages we read opCache = OpBlockedArrayCache(parent=self) opCache.fixAtCurrent.setValue(False) opCache.BlockShape.setValue(page_shape) opCache.Input.connect(opReader.Output) return ([opReader, opCache], opCache.Output)
def setUp(self): self.dataShape = (1, 100, 100, 10, 1) self.data = (numpy.random.random(self.dataShape) * 100).astype(int) self.data = numpy.ma.masked_array(self.data, mask=numpy.ma.getmaskarray( self.data), fill_value=numpy.iinfo(int).max, shrink=False) self.data[:, 0] = numpy.ma.masked graph = Graph() opProvider = OpArrayPiperWithAccessCount(graph=graph) opProvider.Input.meta.axistags = vigra.defaultAxistags('txyzc') opProvider.Input.meta.has_mask = True opProvider.Input.setValue(self.data) self.opProvider = opProvider opCache = OpBlockedArrayCache(graph=graph) opCache.Input.connect(opProvider.Output) opCache.innerBlockShape.setValue((10, 10, 10, 10, 10)) opCache.outerBlockShape.setValue((20, 20, 20, 20, 20)) opCache.fixAtCurrent.setValue(False) self.opCache = opCache
def __init__(self, *args, **kwargs): super(OpThresholdTwoLevels, self).__init__(*args, **kwargs) self.opReorderInput = OpReorderAxes(parent=self) self.opReorderInput.AxisOrder.setValue('tzyxc') self.opReorderInput.Input.connect(self.InputImage) # PROBABILITIES: Convert to float32 self.opConvertProbabilities = OpConvertDtype( parent=self ) self.opConvertProbabilities.ConversionDtype.setValue( np.float32 ) self.opConvertProbabilities.Input.connect( self.opReorderInput.Output ) # PROBABILITIES: Normalize drange to [0.0, 1.0] self.opNormalizeProbabilities = OpPixelOperator( parent=self ) def normalize_inplace(a): drange = self.opNormalizeProbabilities.Input.meta.drange if drange is None or (drange[0] == 0.0 and drange[1] == 1.0): return a a[:] -= drange[0] a[:] = a[:]/float(( drange[1] - drange[0] )) return a self.opNormalizeProbabilities.Input.connect( self.opConvertProbabilities.Output ) self.opNormalizeProbabilities.Function.setValue( normalize_inplace ) self.opSmoother = OpAnisotropicGaussianSmoothing5d(parent=self) self.opSmoother.Sigmas.connect( self.SmootherSigma ) self.opSmoother.Input.connect( self.opNormalizeProbabilities.Output ) self.opSmootherCache = OpBlockedArrayCache(parent=self) self.opSmootherCache.BlockShape.setValue((1, None, None, None, 1)) self.opSmootherCache.Input.connect( self.opSmoother.Output ) self.opCoreChannelSelector = OpSingleChannelSelector(parent=self) self.opCoreChannelSelector.Index.connect( self.CoreChannel ) self.opCoreChannelSelector.Input.connect( self.opSmootherCache.Output ) self.opCoreThreshold = OpLabeledThreshold(parent=self) self.opCoreThreshold.Method.setValue( ThresholdMethod.SIMPLE ) self.opCoreThreshold.FinalThreshold.connect( self.HighThreshold ) self.opCoreThreshold.Input.connect( self.opCoreChannelSelector.Output ) self.opCoreFilter = OpFilterLabels(parent=self) self.opCoreFilter.BinaryOut.setValue(False) self.opCoreFilter.MinLabelSize.connect( self.MinSize ) self.opCoreFilter.MaxLabelSize.connect( self.MaxSize ) self.opCoreFilter.Input.connect( self.opCoreThreshold.Output ) self.opFinalChannelSelector = OpSingleChannelSelector(parent=self) self.opFinalChannelSelector.Index.connect( self.Channel ) self.opFinalChannelSelector.Input.connect( self.opSmootherCache.Output ) self.opSumInputs = OpMultiArrayMerger(parent=self) # see setupOutputs (below) for input connections self.opSumInputs.MergingFunction.setValue( sum ) self.opFinalThreshold = OpLabeledThreshold(parent=self) self.opFinalThreshold.Method.connect( self.CurOperator ) self.opFinalThreshold.FinalThreshold.connect( self.LowThreshold ) self.opFinalThreshold.GraphcutBeta.connect( self.Beta ) self.opFinalThreshold.CoreLabels.connect( self.opCoreFilter.Output ) self.opFinalThreshold.Input.connect( self.opSumInputs.Output ) self.opFinalFilter = OpFilterLabels(parent=self) self.opFinalFilter.BinaryOut.setValue(False) self.opFinalFilter.MinLabelSize.connect( self.MinSize ) self.opFinalFilter.MaxLabelSize.connect( self.MaxSize ) self.opFinalFilter.Input.connect( self.opFinalThreshold.Output ) self.opReorderOutput = OpReorderAxes(parent=self) #self.opReorderOutput.AxisOrder.setValue('tzyxc') # See setupOutputs() self.opReorderOutput.Input.connect(self.opFinalFilter.Output) self.Output.connect( self.opReorderOutput.Output ) self.opCache = OpBlockedArrayCache(parent=self) self.opCache.CompressionEnabled.setValue(True) self.opCache.Input.connect( self.opReorderOutput.Output ) self.CachedOutput.connect( self.opCache.Output ) self.CleanBlocks.connect( self.opCache.CleanBlocks ) ## Debug outputs self.Smoothed.connect( self.opSmootherCache.Output ) self.InputChannel.connect( self.opFinalChannelSelector.Output ) self.SmallRegions.connect( self.opCoreThreshold.Output ) self.FilteredSmallLabels.connect( self.opCoreFilter.Output ) self.BeforeSizeFilter.connect( self.opFinalThreshold.Output ) # Since hysteresis thresholding creates the big regions and immediately discards the bad ones, # we have to recreate it here if the user wants to view it as a debug layer self.opBigRegionsThreshold = OpLabeledThreshold(parent=self) self.opBigRegionsThreshold.Method.setValue( ThresholdMethod.SIMPLE ) self.opBigRegionsThreshold.FinalThreshold.connect( self.LowThreshold ) self.opBigRegionsThreshold.Input.connect( self.opFinalChannelSelector.Output ) self.BigRegions.connect( self.opBigRegionsThreshold.Output )
class OpThresholdTwoLevels(Operator): RawInput = InputSlot(optional=True) # Display only InputChannelColors = InputSlot(optional=True) # Display only InputImage = InputSlot() MinSize = InputSlot(stype='int', value=10) MaxSize = InputSlot(stype='int', value=1000000) HighThreshold = InputSlot(stype='float', value=0.5) LowThreshold = InputSlot(stype='float', value=0.2) SmootherSigma = InputSlot(value={'z': 1.0, 'y': 1.0, 'x': 1.0}) Channel = InputSlot(value=0) CoreChannel = InputSlot(value=0) CurOperator = InputSlot(stype='int', value=ThresholdMethod.SIMPLE) # This slot would be better named 'method', # but we're keeping this slot name for backwards # compatibility with old project files Beta = InputSlot(value=.2) # For GraphCut ## Output slots ## Output = OutputSlot() CachedOutput = OutputSlot() # For the GUI (blockwise-access) # For serialization CacheInput = InputSlot(optional=True) CleanBlocks = OutputSlot() ## Debug outputs InputChannel = OutputSlot() Smoothed = OutputSlot() BigRegions = OutputSlot() SmallRegions = OutputSlot() FilteredSmallLabels = OutputSlot() BeforeSizeFilter = OutputSlot() ## Basic schematic (debug outputs not shown) ## ## InputImage -> opReorder -> opSmoother -> opSmootherCache --> opFinalChannelSelector --> opSumInputs --------------------> opFinalThreshold -> opFinalFilter -> opReorder -> Output ## \ / / \ ## --> opCoreChannelSelector --> opCoreThreshold -> opCoreFilter -- opCache -> CachedOutput ## `-> CleanBlocks def __init__(self, *args, **kwargs): super(OpThresholdTwoLevels, self).__init__(*args, **kwargs) self.opReorderInput = OpReorderAxes(parent=self) self.opReorderInput.AxisOrder.setValue('tzyxc') self.opReorderInput.Input.connect(self.InputImage) # PROBABILITIES: Convert to float32 self.opConvertProbabilities = OpConvertDtype( parent=self ) self.opConvertProbabilities.ConversionDtype.setValue( np.float32 ) self.opConvertProbabilities.Input.connect( self.opReorderInput.Output ) # PROBABILITIES: Normalize drange to [0.0, 1.0] self.opNormalizeProbabilities = OpPixelOperator( parent=self ) def normalize_inplace(a): drange = self.opNormalizeProbabilities.Input.meta.drange if drange is None or (drange[0] == 0.0 and drange[1] == 1.0): return a a[:] -= drange[0] a[:] = a[:]/float(( drange[1] - drange[0] )) return a self.opNormalizeProbabilities.Input.connect( self.opConvertProbabilities.Output ) self.opNormalizeProbabilities.Function.setValue( normalize_inplace ) self.opSmoother = OpAnisotropicGaussianSmoothing5d(parent=self) self.opSmoother.Sigmas.connect( self.SmootherSigma ) self.opSmoother.Input.connect( self.opNormalizeProbabilities.Output ) self.opSmootherCache = OpBlockedArrayCache(parent=self) self.opSmootherCache.BlockShape.setValue((1, None, None, None, 1)) self.opSmootherCache.Input.connect( self.opSmoother.Output ) self.opCoreChannelSelector = OpSingleChannelSelector(parent=self) self.opCoreChannelSelector.Index.connect( self.CoreChannel ) self.opCoreChannelSelector.Input.connect( self.opSmootherCache.Output ) self.opCoreThreshold = OpLabeledThreshold(parent=self) self.opCoreThreshold.Method.setValue( ThresholdMethod.SIMPLE ) self.opCoreThreshold.FinalThreshold.connect( self.HighThreshold ) self.opCoreThreshold.Input.connect( self.opCoreChannelSelector.Output ) self.opCoreFilter = OpFilterLabels(parent=self) self.opCoreFilter.BinaryOut.setValue(False) self.opCoreFilter.MinLabelSize.connect( self.MinSize ) self.opCoreFilter.MaxLabelSize.connect( self.MaxSize ) self.opCoreFilter.Input.connect( self.opCoreThreshold.Output ) self.opFinalChannelSelector = OpSingleChannelSelector(parent=self) self.opFinalChannelSelector.Index.connect( self.Channel ) self.opFinalChannelSelector.Input.connect( self.opSmootherCache.Output ) self.opSumInputs = OpMultiArrayMerger(parent=self) # see setupOutputs (below) for input connections self.opSumInputs.MergingFunction.setValue( sum ) self.opFinalThreshold = OpLabeledThreshold(parent=self) self.opFinalThreshold.Method.connect( self.CurOperator ) self.opFinalThreshold.FinalThreshold.connect( self.LowThreshold ) self.opFinalThreshold.GraphcutBeta.connect( self.Beta ) self.opFinalThreshold.CoreLabels.connect( self.opCoreFilter.Output ) self.opFinalThreshold.Input.connect( self.opSumInputs.Output ) self.opFinalFilter = OpFilterLabels(parent=self) self.opFinalFilter.BinaryOut.setValue(False) self.opFinalFilter.MinLabelSize.connect( self.MinSize ) self.opFinalFilter.MaxLabelSize.connect( self.MaxSize ) self.opFinalFilter.Input.connect( self.opFinalThreshold.Output ) self.opReorderOutput = OpReorderAxes(parent=self) #self.opReorderOutput.AxisOrder.setValue('tzyxc') # See setupOutputs() self.opReorderOutput.Input.connect(self.opFinalFilter.Output) self.Output.connect( self.opReorderOutput.Output ) self.opCache = OpBlockedArrayCache(parent=self) self.opCache.CompressionEnabled.setValue(True) self.opCache.Input.connect( self.opReorderOutput.Output ) self.CachedOutput.connect( self.opCache.Output ) self.CleanBlocks.connect( self.opCache.CleanBlocks ) ## Debug outputs self.Smoothed.connect( self.opSmootherCache.Output ) self.InputChannel.connect( self.opFinalChannelSelector.Output ) self.SmallRegions.connect( self.opCoreThreshold.Output ) self.FilteredSmallLabels.connect( self.opCoreFilter.Output ) self.BeforeSizeFilter.connect( self.opFinalThreshold.Output ) # Since hysteresis thresholding creates the big regions and immediately discards the bad ones, # we have to recreate it here if the user wants to view it as a debug layer self.opBigRegionsThreshold = OpLabeledThreshold(parent=self) self.opBigRegionsThreshold.Method.setValue( ThresholdMethod.SIMPLE ) self.opBigRegionsThreshold.FinalThreshold.connect( self.LowThreshold ) self.opBigRegionsThreshold.Input.connect( self.opFinalChannelSelector.Output ) self.BigRegions.connect( self.opBigRegionsThreshold.Output ) def setupOutputs(self): axes = self.InputImage.meta.getAxisKeys() self.opReorderOutput.AxisOrder.setValue(axes) # Cache individual t,c slices blockshape = tuple(1 if k in 'tc' else None for k in axes) self.opCache.BlockShape.setValue(blockshape) if self.CurOperator.value in (ThresholdMethod.HYSTERESIS, ThresholdMethod.IPHT) \ and self.Channel.value != self.CoreChannel.value: self.opSumInputs.Inputs.resize(2) self.opSumInputs.Inputs[0].connect( self.opFinalChannelSelector.Output ) self.opSumInputs.Inputs[1].connect( self.opCoreChannelSelector.Output ) else: self.opSumInputs.Inputs.resize(1) self.opSumInputs.Inputs[0].connect( self.opFinalChannelSelector.Output ) def setInSlot(self, slot, subindex, roi, value): self.opCache.setInSlot(self.opCache.Input, subindex, roi, value) def execute(self, slot, subindex, roi, destination): assert False, "Shouldn't get here." def propagateDirty(self, slot, subindex, roi): pass # dirtiness propagation is handled in the sub-operators
def connectLane(self, laneIndex): """ Override from base class. """ opDataSelection = self.dataSelectionApplet.topLevelOperator.getLane( laneIndex) opWsdt = self.wsdtApplet.topLevelOperator.getLane(laneIndex) opEdgeTrainingWithMulticut = self.edgeTrainingWithMulticutApplet.topLevelOperator.getLane( laneIndex) opDataExport = self.dataExportApplet.topLevelOperator.getLane( laneIndex) # RAW DATA: Convert to float32 opConvertRaw = OpConvertDtype(parent=self) opConvertRaw.ConversionDtype.setValue(np.float32) opConvertRaw.Input.connect( opDataSelection.ImageGroup[self.DATA_ROLE_RAW]) # PROBABILITIES: Convert to float32 opConvertProbabilities = OpConvertDtype(parent=self) opConvertProbabilities.ConversionDtype.setValue(np.float32) opConvertProbabilities.Input.connect( opDataSelection.ImageGroup[self.DATA_ROLE_PROBABILITIES]) # GROUNDTRUTH: Convert to uint32, relabel, and cache opConvertGroundtruth = OpConvertDtype(parent=self) opConvertGroundtruth.ConversionDtype.setValue(np.uint32) opConvertGroundtruth.Input.connect( opDataSelection.ImageGroup[self.DATA_ROLE_GROUNDTRUTH]) opRelabelGroundtruth = OpRelabelConsecutive(parent=self) opRelabelGroundtruth.Input.connect(opConvertGroundtruth.Output) opGroundtruthCache = OpBlockedArrayCache(parent=self) opGroundtruthCache.CompressionEnabled.setValue(True) opGroundtruthCache.Input.connect(opRelabelGroundtruth.Output) # watershed inputs opWsdt.RawData.connect(opDataSelection.ImageGroup[self.DATA_ROLE_RAW]) opWsdt.Input.connect( opDataSelection.ImageGroup[self.DATA_ROLE_PROBABILITIES]) # Actual computation is done with both RawData and Probabilities opStackRawAndVoxels = OpSimpleStacker(parent=self) opStackRawAndVoxels.Images.resize(2) opStackRawAndVoxels.Images[0].connect(opConvertRaw.Output) opStackRawAndVoxels.Images[1].connect(opConvertProbabilities.Output) opStackRawAndVoxels.AxisFlag.setValue('c') # If superpixels are available from a file, use it. opSuperpixelsSelect = OpPrecomputedInput(ignore_dirty_input=True, parent=self) opSuperpixelsSelect.PrecomputedInput.connect( opDataSelection.ImageGroup[self.DATA_ROLE_SUPERPIXELS]) opSuperpixelsSelect.SlowInput.connect(opWsdt.Superpixels) # If the superpixel file changes, then we have to remove the training labels from the image opEdgeTraining = opEdgeTrainingWithMulticut.opEdgeTraining def handle_new_superpixels(*args): opEdgeTraining.handle_dirty_superpixels(opEdgeTraining.Superpixels) opDataSelection.ImageGroup[self.DATA_ROLE_SUPERPIXELS].notifyReady( handle_new_superpixels) opDataSelection.ImageGroup[self.DATA_ROLE_SUPERPIXELS].notifyUnready( handle_new_superpixels) # edge training inputs opEdgeTrainingWithMulticut.RawData.connect(opDataSelection.ImageGroup[ self.DATA_ROLE_RAW]) # Used for visualization only opEdgeTrainingWithMulticut.VoxelData.connect( opStackRawAndVoxels.Output) opEdgeTrainingWithMulticut.Superpixels.connect( opSuperpixelsSelect.Output) opEdgeTrainingWithMulticut.GroundtruthSegmentation.connect( opGroundtruthCache.Output) # DataExport inputs opDataExport.RawData.connect( opDataSelection.ImageGroup[self.DATA_ROLE_RAW]) opDataExport.RawDatasetInfo.connect( opDataSelection.DatasetGroup[self.DATA_ROLE_RAW]) opDataExport.Inputs.resize(len(self.EXPORT_NAMES)) opDataExport.Inputs[0].connect(opEdgeTrainingWithMulticut.Output) for slot in opDataExport.Inputs: assert slot.partner is not None
if __name__=='__main__': graph = Graph() stack_reader = OpH5StackReader5d(graph) stack_reader.inputs["h5fns"].setValue("pups") stack_reader.inputs["dataset"].setValue("hamster" ) array = OpArrayPiper(graph) fiver = vol.Op5ifyer(graph) fiver.inputs['Input'].connect(array.outputs["Output"]) cache = OpBlockedArrayCache(graph) #cache = OpArrayCache(graph) outerShape = 256 innerShape = 129 cache.inputs['outerBlockShape'].setValue((1,outerShape, outerShape, outerShape,1)) cache.inputs['innerBlockShape'].setValue((1,innerShape, innerShape, innerShape,1)) #cache.inputs['blockShape'].setValue((1,64,64,64,1)) cache.inputs['fixAtCurrent'].setValue(False) cache.inputs["Input"].connect(stack_reader.outputs['array5d']) cache.outputs["Output"][0,:,:,500,0].allocate().wait() import itertools, time
class OpSingleBlockObjectPrediction( Operator ): RawImage = InputSlot() BinaryImage = InputSlot() SelectedFeatures = InputSlot(rtype = List, stype=Opaque) Classifier = InputSlot() LabelsCount = InputSlot() ObjectwisePredictions = OutputSlot(stype=Opaque, rtype=List) PredictionImage = OutputSlot() ProbabilityChannelImage = OutputSlot() BlockwiseRegionFeatures = OutputSlot() # Indexed by (t,c) # Schematic: # # RawImage -----> opRawSubRegion ------ _______________________ # \ / \ # BinaryImage --> opBinarySubRegion --> opExtract --(features)--> opPredict --(map)--> opPredictionImage --via execute()--> PredictionImage # / \ / / # SelectedFeatures----- \ Classifier / # \ / # (labels)---------------------------> opProbabilityChannelsToImage # +----------------------------------------------------------------+ # | input_shape = RawImage.meta.shape | # | | # | | # | | # | | # | | # | | # | halo_shape = blockshape + 2*halo_padding | # | +------------------------+ | # | | halo_roi | | # | | (for internal pipeline)| | # | | | | # | | +------------------+ | | # | | | block_roi | | | # | | | (output shape) | | | # | | | | | | # | | | | | | # | | | | | | # | | +------------------+ | | # | | | | # | | | | # | | | | # | +------------------------+ | # | | # | | # | | # | | # | | # | | # | | # +----------------------------------------------------------------+ def __init__(self, block_roi, halo_padding, *args, **kwargs): super( self.__class__, self ).__init__( *args, **kwargs ) self.block_roi = block_roi # In global coordinates self._halo_padding = halo_padding self._opBinarySubRegion = OpSubRegion( parent=self ) self._opBinarySubRegion.Input.connect( self.BinaryImage ) self._opRawSubRegion = OpSubRegion( parent=self ) self._opRawSubRegion.Input.connect( self.RawImage ) self._opExtract = OpObjectExtraction( parent=self ) self._opExtract.BinaryImage.connect( self._opBinarySubRegion.Output ) self._opExtract.RawImage.connect( self._opRawSubRegion.Output ) self._opExtract.Features.connect(self.SelectedFeatures) self.BlockwiseRegionFeatures.connect( self._opExtract.BlockwiseRegionFeatures ) self._opExtract._opRegFeats._opCache.name = "blockwise-regionfeats-cache" self._opPredict = OpObjectPredict( parent=self ) self._opPredict.Features.connect( self._opExtract.RegionFeatures ) self._opPredict.SelectedFeatures.connect( self.SelectedFeatures ) self._opPredict.Classifier.connect( self.Classifier ) self._opPredict.LabelsCount.connect( self.LabelsCount ) self.ObjectwisePredictions.connect( self._opPredict.Predictions ) self._opPredictionImage = OpRelabelSegmentation( parent=self ) self._opPredictionImage.Image.connect( self._opExtract.LabelImage ) self._opPredictionImage.Features.connect( self._opExtract.RegionFeatures ) self._opPredictionImage.ObjectMap.connect( self._opPredict.Predictions ) self._opPredictionCache = OpBlockedArrayCache( parent=self ) self._opPredictionCache.Input.connect( self._opPredictionImage.Output ) self._opProbabilityChannelsToImage = OpMultiRelabelSegmentation( parent=self ) self._opProbabilityChannelsToImage.Image.connect( self._opExtract.LabelImage ) self._opProbabilityChannelsToImage.ObjectMaps.connect( self._opPredict.ProbabilityChannels ) self._opProbabilityChannelsToImage.Features.connect( self._opExtract.RegionFeatures ) self._opProbabilityChannelStacker = OpMultiArrayStacker( parent=self ) self._opProbabilityChannelStacker.Images.connect( self._opProbabilityChannelsToImage.Output ) self._opProbabilityChannelStacker.AxisFlag.setValue('c') self._opProbabilityCache = OpBlockedArrayCache( parent=self ) self._opProbabilityCache.Input.connect( self._opProbabilityChannelStacker.Output ) def setupOutputs(self): tagged_input_shape = self.RawImage.meta.getTaggedShape() self._halo_roi = self.computeHaloRoi( tagged_input_shape, self._halo_padding, self.block_roi ) # In global coordinates # Output roi in our own coordinates (i.e. relative to the halo start) self._output_roi = self.block_roi - self._halo_roi[0] halo_start, halo_stop = list(map(tuple, self._halo_roi)) self._opRawSubRegion.Roi.setValue( (halo_start, halo_stop) ) # Binary image has only 1 channel. Adjust halo subregion. assert self.BinaryImage.meta.getTaggedShape()['c'] == 1 c_index = self.BinaryImage.meta.axistags.channelIndex binary_halo_roi = numpy.array(self._halo_roi) binary_halo_roi[:, c_index] = (0,1) # Binary has only 1 channel. binary_halo_start, binary_halo_stop = list(map(tuple, binary_halo_roi)) self._opBinarySubRegion.Roi.setValue( (binary_halo_start, binary_halo_stop) ) self.PredictionImage.meta.assignFrom( self._opPredictionImage.Output.meta ) self.PredictionImage.meta.shape = tuple( numpy.subtract( self.block_roi[1], self.block_roi[0] ) ) self.ProbabilityChannelImage.meta.assignFrom( self._opProbabilityChannelStacker.Output.meta ) probability_shape = numpy.subtract( self.block_roi[1], self.block_roi[0] ) probability_shape[-1] = self._opProbabilityChannelStacker.Output.meta.shape[-1] self.ProbabilityChannelImage.meta.shape = tuple(probability_shape) # Cache the entire block self._opPredictionCache.BlockShape.setValue( self._opPredictionCache.Input.meta.shape ) self._opProbabilityCache.BlockShape.setValue( self._opProbabilityCache.Input.meta.shape ) # Forward dirty regions to our own output self._opPredictionImage.Output.notifyDirty( self._handleDirtyPrediction ) def execute(self, slot, subindex, roi, destination): assert slot is self.PredictionImage or slot is self.ProbabilityChannelImage, "Unknown input slot" assert (numpy.array(roi.stop) <= slot.meta.shape).all(), "Roi is out-of-bounds" # Extract from the output (discard halo) halo_offset = numpy.subtract(self.block_roi[0], self._halo_roi[0]) adjusted_roi = ( halo_offset + roi.start, halo_offset + roi.stop ) if slot is self.PredictionImage: return self._opPredictionCache.Output(*adjusted_roi).writeInto(destination).wait() elif slot is self.ProbabilityChannelImage: return self._opProbabilityCache.Output(*adjusted_roi).writeInto(destination).wait() def propagateDirty(self, slot, subindex, roi): """ Nothing to do here because dirty notifications are propagated through our internal pipeline and forwarded to our output via our notifyDirty handler. """ pass def _handleDirtyPrediction(self, slot, roi): """ Foward dirty notifications from our internal output slot to the external one, but first discard the halo and offset the roi to compensate for the halo. """ # Discard halo. dirtyRoi is in internal coordinates (i.e. relative to halo start) dirtyRoi = getIntersection( (roi.start, roi.stop), self._output_roi, assertIntersect=False ) if dirtyRoi is not None: halo_offset = numpy.subtract(self.block_roi[0], self._halo_roi[0]) adjusted_roi = dirtyRoi - halo_offset # adjusted_roi is in output coordinates (relative to output block start) self.PredictionImage.setDirty( *adjusted_roi ) # Expand to all channels and set channel image dirty adjusted_roi[:,-1] = (0, self.ProbabilityChannelImage.meta.shape[-1]) self.ProbabilityChannelImage.setDirty( *adjusted_roi ) @classmethod def computeHaloRoi(cls, tagged_dataset_shape, halo_padding, block_roi): block_roi = numpy.array(block_roi) block_start, block_stop = block_roi channel_index = list(tagged_dataset_shape.keys()).index('c') block_start[ channel_index ] = 0 block_stop[ channel_index ] = tagged_dataset_shape['c'] # Compute halo and clip to dataset bounds halo_start = block_start - halo_padding halo_start = numpy.maximum( halo_start, (0,)*len(halo_start) ) halo_stop = block_stop + halo_padding halo_stop = numpy.minimum( halo_stop, list(tagged_dataset_shape.values()) ) halo_roi = (halo_start, halo_stop) return halo_roi