def __init__(self, parent=None, graph=None): super(OpTrackingBase, self).__init__(parent=parent, graph=graph) self.label2color = [] self.mergers = [] self.resolvedto = [] self.track_id = None self.extra_track_ids = None self.divisions = None self._opCache = OpCompressedCache(parent=self) self._opCache.InputHdf5.connect(self.InputHdf5) self._opCache.Input.connect(self.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks) self.OutputHdf5.connect(self._opCache.OutputHdf5) 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.export_progress_dialog = None self.ExportSettings.setValue((None, None))
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, 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 setupOutputs(self): self.Output.meta.assignFrom(self.LabelImage.meta) #cache our own output, don't propagate from internal operator chunks = list(self.LabelImage.meta.shape) # FIXME: assumes t,x,y,z,c chunks[0] = 1 # 't' self._opCache = OpCompressedCache(parent=self) self._opCache.InputHdf5.connect(self.InputHdf5) self._opCache.Input.connect(self.Output) self._opCache.BlockShape.setValue(tuple(chunks)) self.CleanBlocks.connect(self._opCache.CleanBlocks) self.OutputHdf5.connect(self._opCache.OutputHdf5) self.CachedOutput.connect(self._opCache.Output) self.zeroProvider = OpZeroDefault(parent=self) self.zeroProvider.MetaInput.connect(self.LabelImage)
def __init__(self, parent=None, graph=None): super(OpTrackingBase, self).__init__(parent=parent, graph=graph) self.label2color = [] self.mergers = [] self._opCache = OpCompressedCache(parent=self) self._opCache.InputHdf5.connect(self.InputHdf5) self._opCache.Input.connect(self.Output) self.CleanBlocks.connect(self._opCache.CleanBlocks) self.OutputHdf5.connect(self._opCache.OutputHdf5) 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)
def setupOutputs(self): self.internalCleanup() datasetInfo = self.Dataset.value try: # Data only comes from the project file if the user said so AND it exists in the project datasetInProject = ( datasetInfo.location == DatasetInfo.Location.ProjectInternal) datasetInProject &= self.ProjectFile.ready() if datasetInProject: internalPath = self.ProjectDataGroup.value + '/' + datasetInfo.datasetId datasetInProject &= internalPath in self.ProjectFile.value # If we should find the data in the project file, use a dataset reader if datasetInProject: opReader = OpStreamingH5N5Reader(parent=self) opReader.H5N5File.setValue(self.ProjectFile.value) opReader.InternalPath.setValue(internalPath) providerSlot = opReader.OutputImage elif datasetInfo.location == DatasetInfo.Location.PreloadedArray: preloaded_array = datasetInfo.preloaded_array assert preloaded_array is not None if not hasattr(preloaded_array, 'axistags'): axisorder = get_default_axisordering(preloaded_array.shape) preloaded_array = vigra.taggedView(preloaded_array, axisorder) opReader = OpArrayPiper(parent=self) opReader.Input.setValue(preloaded_array) providerSlot = opReader.Output else: if datasetInfo.realDataSource: # Use a normal (filesystem) reader opReader = OpInputDataReader(parent=self) if datasetInfo.subvolume_roi is not None: opReader.SubVolumeRoi.setValue( datasetInfo.subvolume_roi) opReader.WorkingDirectory.setValue( self.WorkingDirectory.value) opReader.SequenceAxis.setValue(datasetInfo.sequenceAxis) opReader.FilePath.setValue(datasetInfo.filePath) else: # Use fake reader: allows to run the project in a headless # mode without the raw data opReader = OpZeroDefault(parent=self) opReader.MetaInput.meta = MetaDict( shape=datasetInfo.laneShape, dtype=datasetInfo.laneDtype, drange=datasetInfo.drange, axistags=datasetInfo.axistags) opReader.MetaInput.setValue( numpy.zeros(datasetInfo.laneShape, dtype=datasetInfo.laneDtype)) providerSlot = opReader.Output self._opReaders.append(opReader) # Inject metadata if the dataset info specified any. # Also, inject if if dtype is uint8, which we can reasonably assume has drange (0,255) metadata = {} metadata['display_mode'] = datasetInfo.display_mode role_name = self.RoleName.value if 'c' not in providerSlot.meta.getTaggedShape(): num_channels = 0 else: num_channels = providerSlot.meta.getTaggedShape()['c'] if num_channels > 1: metadata['channel_names'] = [ "{}-{}".format(role_name, i) for i in range(num_channels) ] else: metadata['channel_names'] = [role_name] if datasetInfo.drange is not None: metadata['drange'] = datasetInfo.drange elif providerSlot.meta.dtype == numpy.uint8: # SPECIAL case for uint8 data: Provide a default drange. # The user can always override this herself if she wants. metadata['drange'] = (0, 255) if datasetInfo.normalizeDisplay is not None: metadata['normalizeDisplay'] = datasetInfo.normalizeDisplay if datasetInfo.axistags is not None: if len(datasetInfo.axistags) != len(providerSlot.meta.shape): ts = providerSlot.meta.getTaggedShape() if 'c' in ts and 'c' not in datasetInfo.axistags and len( datasetInfo.axistags) + 1 == len(ts): # provider has no channel axis, but template has => add channel axis to provider # fixme: Optimize the axistag guess in BatchProcessingApplet instead of hoping for the best here metadata['axistags'] = vigra.defaultAxistags( ''.join(datasetInfo.axistags.keys()) + 'c') else: # This usually only happens when we copied a DatasetInfo from another lane, # and used it as a 'template' to initialize this lane. # This happens in the BatchProcessingApplet when it attempts to guess the axistags of # batch images based on the axistags chosen by the user in the interactive images. # If the interactive image tags don't make sense for the batch image, you get this error. raise Exception( "Your dataset's provided axistags ({}) do not have the " "correct dimensionality for your dataset, which has {} dimensions." .format( "".join(tag.key for tag in datasetInfo.axistags), len(providerSlot.meta.shape))) else: metadata['axistags'] = datasetInfo.axistags if datasetInfo.original_axistags is not None: metadata['original_axistags'] = datasetInfo.original_axistags if datasetInfo.subvolume_roi is not None: metadata['subvolume_roi'] = datasetInfo.subvolume_roi # FIXME: We are overwriting the axistags metadata to intentionally allow # the user to change our interpretation of which axis is which. # That's okay, but technically there's a special corner case if # the user redefines the channel axis index. # Technically, it invalidates the meaning of meta.ram_usage_per_requested_pixel. # For most use-cases, that won't really matter, which is why I'm not worrying about it right now. opMetadataInjector = OpMetadataInjector(parent=self) opMetadataInjector.Input.connect(providerSlot) opMetadataInjector.Metadata.setValue(metadata) providerSlot = opMetadataInjector.Output self._opReaders.append(opMetadataInjector) self._NonTransposedImage.connect(providerSlot) # make sure that x and y axes are present in the selected axis order if 'x' not in providerSlot.meta.axistags or 'y' not in providerSlot.meta.axistags: raise DatasetConstraintError( "DataSelection", "Data must always have at leaset the axes x and y for ilastik to work." ) if self.forceAxisOrder: assert isinstance(self.forceAxisOrder, list), \ "forceAxisOrder should be a *list* of preferred axis orders" # Before we re-order, make sure no non-singleton # axes would be dropped by the forced order. tagged_provider_shape = providerSlot.meta.getTaggedShape() minimal_axes = [ k_v for k_v in list(tagged_provider_shape.items()) if k_v[1] > 1 ] minimal_axes = set(k for k, v in minimal_axes) # Pick the shortest of the possible 'forced' orders that # still contains all the axes of the original dataset. candidate_orders = list(self.forceAxisOrder) candidate_orders = [ order for order in candidate_orders if minimal_axes.issubset(set(order)) ] if len(candidate_orders) == 0: msg = "The axes of your dataset ({}) are not compatible with any of the allowed"\ " axis configurations used by this workflow ({}). Please fix them."\ .format(providerSlot.meta.getAxisKeys(), self.forceAxisOrder) raise DatasetConstraintError("DataSelection", msg) output_order = sorted(candidate_orders, key=len)[0] # the shortest one output_order = "".join(output_order) else: # No forced axisorder is supplied. Use original axisorder as # output order: it is assumed by the export-applet, that the # an OpReorderAxes operator is added in the beginning output_order = "".join( [x for x in providerSlot.meta.axistags.keys()]) op5 = OpReorderAxes(parent=self) op5.AxisOrder.setValue(output_order) op5.Input.connect(providerSlot) providerSlot = op5.Output self._opReaders.append(op5) # If the channel axis is missing, add it as last axis if 'c' not in providerSlot.meta.axistags: op5 = OpReorderAxes(parent=self) keys = providerSlot.meta.getAxisKeys() # Append keys.append('c') op5.AxisOrder.setValue("".join(keys)) op5.Input.connect(providerSlot) providerSlot = op5.Output self._opReaders.append(op5) # Connect our external outputs to the internal operators we chose self.Image.connect(providerSlot) self.AllowLabels.setValue(datasetInfo.allowLabels) # If the reading operator provides a nickname, use it. if self.Image.meta.nickname is not None: datasetInfo.nickname = self.Image.meta.nickname imageName = datasetInfo.nickname if imageName == "": imageName = datasetInfo.filePath self.ImageName.setValue(imageName) except: self.internalCleanup() raise