class TestOutputOutputConnection(object): def setUp(self): self.g = Graph() self.op = OpOuter(graph=self.g) def tearDown(self): self.g.stopGraph() def test_value(self): """ This test checks, that requests produce correct results in the case of output-output connections (the o-o connection exists inside the OpOuter... """ self.op.Input.setValue(True) result = self.op.Output[:].wait()[0] assert result == True, "result = %r" % result self.op.Input.setValue(False) result = self.op.Output[:].wait()[0] assert result == False, "result = %r" % result def test_execute(self): """ This test checks that the execute method of the outer operator is not called, when the output slot of the op is connect to the output slot of another (inner) operator """ self.op.Input.setValue(True) self.op._was_executed = False result = self.op.Output[:].wait()[0] assert self.op._was_executed is False
class TestSlot_notifyMetaChanged(object): def setUp(self): self.g = Graph() def tearDown(self): self.g.stopGraph() def test_inputslot_changed(self): # test that the changed callback is called # when the slot meta information changes ops = OpS(graph=self.g) opa = OpA(graph=self.g) upval = [False] def callBack(slot): upval[0] = True # test normal InputSlot opa.Input1.notifyMetaChanged(callBack) opa.Input1.connect(ops.Output1) assert upval[0] == True upval[0] = False opa.Input1.connect(ops.Output2) assert upval[0] == True # test InputSlot with default value upval[0] = False opa.Input3.notifyMetaChanged(callBack) opa.Input3.connect(ops.Output1) assert upval[0] == True upval[0] = False
def __init__(self, argv): QMainWindow.__init__(self) #Normalize the data if true self._normalize_data=True if 'notnormalize' in sys.argv: print sys.argv self._normalize_data=False sys.argv.remove('notnormalize') self.opPredict = None self.opTrain = None self.opThreshold = None self._colorTable16 = self._createDefault16ColorColorTable() #self.g = Graph(7, 2048*1024**2*5) self.g = Graph() self.fixableOperators = [] self.featureDlg=None #The old ilastik provided the following scale names: #['Tiny', 'Small', 'Medium', 'Large', 'Huge', 'Megahuge', 'Gigahuge'] #The corresponding scales are: self.featScalesList=[0.3, 0.7, 1, 1.6, 3.5, 5.0, 10.0] self.initUic() #if the filename was specified on command line, load it if len(sys.argv) >= 2: def loadFile(): self._openFile(sys.argv[1:]) QTimer.singleShot(0, loadFile)
class TestMultiInputInputConnection(object): def setUp(self): self.g = Graph() self.op = OpC(graph=self.g) def tearDown(self): self.g.stopGraph() def test_wrapping(self): opm = operators.Op5ToMulti(graph=self.g) opm.Input0.setValue(1) self.op.Input.connect(opm.Outputs) assert len(self.op.internalOp.Output) == 1 assert self.op.internalOp.Output[0].meta.shape is not None assert self.op.internalOp.Output[0].value == 1
class TestInputInputConnection(object): def setUp(self): self.g = Graph() self.op = OpA(graph=self.g) def tearDown(self): self.g.stopGraph() def test_value(self): self.op.Input.setValue(True) result = self.op.Output[:].allocate().wait()[0] assert result == True, "result = %r" % result self.op.Input.setValue(False) result = self.op.Output[:].allocate().wait()[0] assert result == False, "result = %r" % result def test_disconnect(self): self.op.internalOp.Input.disconnect() self.op.internalOp.Input.connect(self.op.Input) def test_wrapping(self): opm = operators.Op5ToMulti(graph=self.g) opm.Input0.setValue(1) op = OperatorWrapper( OpA, graph=self.g ) op.Input.connect(opm.Outputs) result = op.Output[0][:].allocate().wait()[0] assert result == 1 opm.Input1.setValue(2) result = op.Output[1][:].allocate().wait()[0] assert result == 2 # Note: operator wrappers do not "restore" back to unwrapped operators after disconnect # (That was their behavior at some point, but no longer.) op.Input.disconnect() op.Input.resize(0) op.Input.setValue(2) assert len(op.Input) == 0 assert len(op.Output) == 0
def testReportGeneration(self): graph = Graph() sampleData = numpy.random.randint(0, 256, size=(50, 50, 50)) sampleData = sampleData.astype(numpy.uint8) sampleData = vigra.taggedView(sampleData, axistags="xyz") opData = OpArrayPiper(graph=graph) opData.Input.setValue(sampleData) op = OpCompressedCache(parent=None, graph=graph) op.BlockShape.setValue((25, 25, 25)) op.Input.connect(opData.Output) before = time.time() assert op.Output.ready() assert op.usedMemory() == 0.0, "cache must not be filled at this point" op.Output[...].wait() assert op.usedMemory() > 0.0, "cache must contain data at this point" after = time.time() r = MemInfoNode() op.generateReport(r) # not sure how good this can be compressed, but the cache # should hold memory by now assert r.usedMemory > 0 # check sanity of last access time assert r.lastAccessTime >= before, str(r.lastAccessTime) assert r.lastAccessTime <= after, str(r.lastAccessTime) assert r.fractionOfUsedMemoryDirty == 0.0 opData.Input.setDirty((slice(0, 25), slice(0, 25), slice(0, 25))) assert op.fractionOfUsedMemoryDirty() < 1.0 assert op.fractionOfUsedMemoryDirty() > 0 opData.Input.setDirty(slice(None)) assert op.fractionOfUsedMemoryDirty() == 1.0
def test_3d_with_compression(self, tmp_path): """ This tests that we can read a compressed (LZW) TIFF file. Note: It would be nice to test JPEG compression here, but strangely when vigra writes a JPEG-compressed TIFF, it is somehow messed up. The image has two image 'series' in it, so the thing seems to have twice as many planes as it should. Furthermore, vigra doesn't seem to read it back correctly, or maybe I'm missing something... """ data = numpy.random.randint(0, 255, (50, 100, 200, 3), dtype="uint8") tiff_path = str(tmp_path / "test-3d.tiff") for z_slice in data: vigra.impex.writeImage(vigra.taggedView(z_slice, "yxc"), tiff_path, dtype="NATIVE", compression="LZW", mode="a") op = OpTiffReader(graph=Graph()) op.Filepath.setValue(tiff_path) assert op.Output.ready() assert (op.Output[20:30, 50:100, 50:150].wait() == data[20:30, 50:100, 50:150]).all()
def __init__( self, *, filePath: str, project_file: h5py.File = None, sequence_axis: str = None, nickname: str = "", drange: Tuple[Number, Number] = None, **info_kwargs, ): """ sequence_axis: Axis along which to stack (only applicable for stacks). """ self.sequence_axis = sequence_axis self.base_dir = str(Path(project_file.filename).absolute().parent) if project_file else os.getcwd() assert os.path.isabs(self.base_dir) # FIXME: if file_project was opened as a relative path, this would break self.expanded_paths = self.expand_path(filePath, cwd=self.base_dir) assert len(self.expanded_paths) == 1 or self.sequence_axis if len({PathComponents(ep).extension for ep in self.expanded_paths}) > 1: raise Exception(f"Multiple extensions unsupported as a single data source: {self.expanded_paths}") self.filePath = os.path.pathsep.join(self.expanded_paths) op_reader = OpInputDataReader( graph=Graph(), WorkingDirectory=self.base_dir, FilePath=self.filePath, SequenceAxis=self.sequence_axis ) meta = op_reader.Output.meta.copy() op_reader.cleanUp() super().__init__( default_tags=meta.axistags, nickname=nickname or self.create_nickname(self.expanded_paths), laneShape=meta.shape, laneDtype=meta.dtype, drange=drange or meta.get("drange"), **info_kwargs, )
def test_hysteresis(self): data = self.data core_binary = (data == 5) core_labels = np.empty_like(data, dtype=np.uint32) core_labels[0, ..., 0] = vigra.analysis.labelMultiArrayWithBackground( core_binary[0, ..., 0].astype(np.uint8)) op = OpLabeledThreshold(graph=Graph()) op.Method.setValue(ThresholdMethod.HYSTERESIS) op.FinalThreshold.setValue(0.5) op.Input.setValue(data.copy()) op.CoreLabels.setValue(core_labels) result = op.Output[:].wait() label_values = np.unique(result)[1:] assert len(label_values) == 1 expected_result = np.where(data, label_values[0], 0) expected_result[0, :, 5:, 0, 0] = 0 # Right half won't survive #print expected_result[0,:,:,0,0] #print result[0,:,:,0,0] assert (result == expected_result).all()
def create_input(cls, filepath, input_axes, outmin=None, outmax=None, dtype=None): """ Creates a file from the data at 'filepath' that has 'input_axes' """ basename = os.path.basename(filepath) reader = OpInputDataReader(graph=Graph()) assert os.path.exists(filepath), '{} not found'.format(filepath) reader.FilePath.setValue(os.path.abspath(filepath)) writer = OpFormattedDataExport(parent=reader) if outmin is not None: writer.ExportMin.setValue(outmin) if outmax is not None: writer.ExportMax.setValue(outmax) if dtype is not None: writer.ExportDtype.setValue(dtype) writer.OutputAxisOrder.setValue(input_axes) writer.Input.connect(reader.Output) writer.OutputFilenameFormat.setValue(os.path.join( cls.dir, basename.split('.')[0] + '_' + input_axes)) writer.TransactionSlot.setValue(True) input_path = writer.ExportPath.value writer.run_export() return input_path
def __init__(self, headless, workflow_cmdline_args, *args, **kwargs): # Create a graph to be shared by all operators graph = Graph() super(StopWatchWorkflow, self).__init__(headless, graph=graph, *args, **kwargs) #self.name = OperatorWrapper(OpName( graph=graph) #self.name.Output[0].setValue("void") self._applets = [] # Create applets self.dataSelectionApplet = DataSelectionApplet( self, "Input Data", "Input Data", supportIlastik05Import=True, batchDataGui=False) self.stopWatchApplet = StopWatchApplet(self, "Stop Watch", "Stop Watch") self._applets.append(self.dataSelectionApplet) self._applets.append(self.stopWatchApplet)
def test_graphcut(self): if _has_graphcut: data = self.data # Core labels don't matter in this graphcut test #core_binary = (data == 5) core_labels = np.empty_like(data, dtype=np.uint32) #core_labels[0,...,0] = vigra.analysis.labelMultiArrayWithBackground(core_binary[0,...,0].astype(np.uint8)) op = OpLabeledThreshold(graph=Graph()) op.Method.setValue(ThresholdMethod.GRAPHCUT) op.FinalThreshold.setValue(0.5) op.Input.setValue(data.copy()) op.CoreLabels.setValue(core_labels) op.GraphcutBeta.setValue(0.5) # High enough to fill the hole in the third segment result = op.Output[:].wait() result_yx = result[0,:,:,0,0] #print result_yx label_values = np.unique(result)[1:] assert len(label_values) == 3 assert len(np.unique(result_yx[1:12, 1:5])) == 1 # Same as 'simple' assert len(np.unique(result_yx[7:10, 6:9])) == 1 # Almost same as simple, but with the hole filled in.
def testReconnect(self): """ Can we connect an image, then replace it with a differently-ordered image? """ predRaw = np.zeros((20, 22, 21, 3), dtype=np.uint32) pred1 = vigra.taggedView(predRaw, axistags='zyxc') pred2 = vigra.taggedView(predRaw, axistags='tyxc') oper5d = OpThresholdTwoLevels(graph=Graph()) oper5d.InputImage.setValue(pred1) oper5d.MinSize.setValue(self.minSize) oper5d.MaxSize.setValue(self.maxSize) oper5d.HighThreshold.setValue(self.highThreshold) oper5d.LowThreshold.setValue(self.lowThreshold) oper5d.SmootherSigma.setValue(self.sigma) oper5d.Channel.setValue(0) oper5d.CoreChannel.setValue(0) oper5d.CurOperator.setValue(1) out5d = oper5d.CachedOutput[:].wait() oper5d.InputImage.disconnect() # FIXME: Why is this line necessary? Ideally, it shouldn't be... oper5d.InputImage.setValue(pred2) out5d = oper5d.CachedOutput[:].wait()
def testSetInSlot(self): graph = Graph() opDataProvider = OpArrayPiperWithAccessCount(graph=graph) opCache = OpUnblockedArrayCache(graph=graph) data = np.random.random((100, 100, 100)).astype(np.float32) opDataProvider.Input.setValue(vigra.taggedView(data, "zyx")) opCache.Input.connect(opDataProvider.Output) # Write two blocks opCache.Input[10:20, 10:20, 10:20] = 2 * np.ones((10, 10, 10), dtype=np.float32) opCache.Input[20:30, 20:30, 20:30] = 3 * np.ones((10, 10, 10), dtype=np.float32) # They should be valid now assert opCache.CleanBlocks.value == [tuple(make_key[10:20, 10:20, 10:20]), tuple(make_key[20:30, 20:30, 20:30])] assert (opCache.Output[10:20, 10:20, 10:20].wait() == 2).all() assert (opCache.Output[20:30, 20:30, 20:30].wait() == 3).all() # Mark a big dirty area opDataProvider.Input.setDirty((10, 10, 10), (40, 40, 40)) # No blocks left in the cache assert opCache.CleanBlocks.value == []
def testDirtyPropagation(self): g = Graph() vol = np.asarray( [[0, 0, 0, 0], [0, 0, 1, 1], [0, 1, 0, 1], [0, 1, 0, 1]], dtype=np.uint8) vol = vigra.taggedView(vol, axistags='xy').withAxes(*'xyz') chunkShape = (2, 2, 1) opCache = OpCompressedCache(graph=g) opCache.Input.setValue(vol) opCache.BlockShape.setValue(chunkShape) op = OpLazyCC(graph=g) op.Input.connect(opCache.Output) op.ChunkShape.setValue(chunkShape) out1 = op.Output[:2, :2].wait() assert np.all(out1 == 0) opCache.Input[0:1, 0:1, 0:1] = np.asarray([[[1]]], dtype=np.uint8) out2 = op.Output[:1, :1].wait() assert np.all(out2 > 0)
def testEvenFunnierAxes(self): vol = numpy.random.randint(0, 255, size=(5, 17, 31, 42, 11)) vol = vol.astype(numpy.uint8) # don't care about corner cases vol[vol == 128] = 129 vol[vol == 127] = 126 desiredResult = numpy.where(vol > 128, 1, 0) vol = vigra.taggedView(vol, axistags='xtycz') oper5d = OpThresholdTwoLevels(graph=Graph()) oper5d.InputImage.setValue(vol) oper5d.MinSize.setValue(1) oper5d.MaxSize.setValue(vol.size) oper5d.LowThreshold.setValue(128) oper5d.SmootherSigma.setValue({'z': 0.0, 'y': 0.0, 'x': 0.0}) oper5d.CurOperator.setValue(self.curOperator) #for i in range(vol.shape[3]): for i in range(2, 5): # just test some sample slices (runtime :) oper5d.Channel.setValue(i) oper5d.CoreChannel.setValue(i) out5d = oper5d.Output[:].wait() out5d[out5d > 0] = 1 numpy.testing.assert_array_equal(out5d.squeeze(), desiredResult[..., i, :])
def test_xyz_stack_c(self): # expected_volume_zyxc, globstring = self._prepare_data_zyx_stack_c() expected_volume, globstring = self._prepare_data( 'rand_3d_stack_c', (2, 3, 5, 4), 'czxy', 'c' ) graph = Graph() op = OpStackLoader(graph=graph) op.SequenceAxis.setValue('c') op.globstring.setValue(globstring) assert len(op.stack.meta.axistags) == 4 assert op.stack.meta.getAxisKeys() == list('czyx') assert op.stack.meta.dtype == expected_volume.dtype volume_from_stack = op.stack[:].wait() volume_from_stack = vigra.taggedView(volume_from_stack, 'czyx') volume_from_stack = volume_from_stack.withAxes(*'czxy') assert (volume_from_stack == expected_volume).all(), \ "3D Volume stacked along c did not match expected data."
def testReconnectWithoutRequest_masked(self): vol = numpy.ma.zeros((200, 100, 50), dtype=numpy.float32) vol.set_fill_value(numpy.float32(numpy.nan)) vol[0] = numpy.ma.masked vol1 = vol vol2 = vol1.T graph = Graph() opData1 = OpArrayPiper(graph=graph) opData1.Input.meta.has_mask = True opData1.Input.meta.axistags = vigra.defaultAxistags('xyz') opData1.Input.setValue(vol1) op = OpCompressedCache(graph=graph) op.Input.connect(opData1.Output) op.BlockShape.setValue((200, 100, 10)) out = op.Output[...].wait() assert (out == vol).all() and \ (out.mask == vol.mask).all() and \ ((out.fill_value == vol.fill_value) | (numpy.isnan(out.fill_value) & numpy.isnan(vol.fill_value))).all(),\ "Incorrect output!" op.BlockShape.setValue((50, 100, 10)) # Older versions of OpCompressedCache threw an exception here because # we tried to access the cache after changing the blockshape. # But in the current version, we claim that's okay. out = op.Output[...].wait() assert (out == vol).all() and \ (out.mask == vol.mask).all() and \ ((out.fill_value == vol.fill_value) | (numpy.isnan(out.fill_value) & numpy.isnan(vol.fill_value))).all(),\ "Incorrect output!"
def setUp(self): segimg = segImage() binimg = (segimg>0).astype(np.uint8) labels = {0 : np.array([0, 1, 2]), 1 : np.array([0, 1, 1, 2])} rawimg = np.indices(segimg.shape).sum(0).astype(np.float32) rawimg = rawimg.view(vigra.VigraArray) rawimg.axistags = vigra.defaultAxistags('txyzc') g = Graph() features = {"Standard Object Features": {"Count":{}, "RegionCenter":{}, "Coord<Principal<Kurtosis>>":{}, \ "Coord<Minimum>":{}, "Coord<Maximum>":{}, "Mean":{}, \ "Mean in neighborhood":{"margin":(30, 30, 1)}}} sel_features = {"Standard Object Features": {"Count":{}, "Mean":{}, "Mean in neighborhood":{"margin":(30, 30, 1)}, "Variance":{}}} self.extrOp = OpObjectExtraction(graph=g) self.extrOp.BinaryImage.setValue(binimg) self.extrOp.RawImage.setValue(rawimg) self.extrOp.Features.setValue(features) assert self.extrOp.RegionFeatures.ready() self.trainop = OpObjectTrain(graph=g) self.trainop.Features.resize(1) self.trainop.Features.connect(self.extrOp.RegionFeatures) self.trainop.SelectedFeatures.setValue(sel_features) self.trainop.LabelsCount.setValue(2) self.trainop.Labels.resize(1) self.trainop.Labels.setValues([labels]) self.trainop.FixClassifier.setValue(False) self.trainop.ForestCount.setValue(1) assert self.trainop.Classifier.ready()
def testSingletonZ(self): vol = np.zeros((82, 70, 1, 5, 5), dtype=np.uint8) vol = vigra.taggedView(vol, axistags="xyzct") blocks = np.zeros(vol.shape, dtype=np.uint8) blocks[30:50, 40:60, :, 2:4, 3:5] = 1 blocks[30:50, 40:60, :, 2:4, 0:2] = 2 blocks[60:70, 30:40, :, :, :] = 3 vol[blocks == 1] = 255 vol[blocks == 2] = 255 vol[blocks == 3] = 255 op = OpLabelVolume(graph=Graph()) op.Method.setValue(self.method) op.Input.setValue(vol) out = op.Output[...].wait() tags = op.Output.meta.getTaggedShape() out = vigra.taggedView(out, axistags="".join([s for s in tags])) for c in range(out.shape[3]): for t in range(out.shape[4]): assertEquivalentLabeling(blocks[..., c, t], out[..., c, t])
def testBasic(self): graph = Graph() op = OpTiledVolumeReader(graph=graph) op.DescriptionFilePath.setValue( self.data_setup.VOLUME_DESCRIPTION_FILE) op.tiled_volume.TEST_MODE = True roi = numpy.array([(10, 150, 100), (30, 550, 550)]) result_out = op.Output(*roi).wait() # We expect a channel dimension to be added automatically... assert (result_out.shape == roi[1] - roi[0]).all() ref_path_comp = PathComponents(self.data_setup.REFERENCE_VOL_PATH) with h5py.File(ref_path_comp.externalPath, "r") as f: ref_data = f[ref_path_comp.internalPath][:] expected = ref_data[roiToSlice(*roi)] # numpy.save('/tmp/expected.npy', expected) # numpy.save('/tmp/result_out.npy', result_out) # We can't expect the pixels to match exactly because compression was used to create the tiles... assert (expected == result_out).all()
def testNoOp(self): oper5d = OpThresholdTwoLevels(graph=Graph()) oper5d.InputImage.setValue(self.data5d) oper5d.MinSize.setValue(1) oper5d.MaxSize.setValue(self.data5d.size) oper5d.LowThreshold.setValue(-0.01) oper5d.SmootherSigma.setValue({'z': 0.0, 'y': 0.0, 'x': 0.0}) oper5d.Channel.setValue(0) oper5d.CoreChannel.setValue(0) oper5d.CurOperator.setValue(self.curOperator) out5d = oper5d.Output[:].wait() numpy.testing.assert_array_equal(out5d.shape, self.data5d.shape) # the image should be white, because of negative threshold assert numpy.all(out5d > 0),\ "{}% elements <= 0".format((out5d <= 0).sum()/float(out5d.size)*100) oper5d.LowThreshold.setValue(1.01) out5d = oper5d.Output[:].wait() # the image should be black, because of threshold larger than 1 assert numpy.all(out5d == 0),\ "{}% elements > 0".format((out5d > 0).sum()/float(out5d.size)*100)
def testBasic(self): tmpdir = tempfile.mkdtemp() try: filepath = tmpdir + "/random_data.klb" shape = (1, 1, 30, 40, 50) data_tczyx = np.indices(shape).sum(0).astype(np.uint8) pyklb.writefull(data_tczyx, filepath, blocksize_xyzct=np.array([10, 10, 10, 1, 1], dtype=np.uint32)) readback = pyklb.readroi(filepath, (0, 0, 0, 0, 0), np.array(shape) - 1) op = OpKlbReader(graph=Graph()) op.FilePath.setValue(filepath) assert op.Output.meta.shape == shape assert op.Output.meta.dtype == np.uint8 read_data = op.Output[:].wait() assert (read_data == data_tczyx).all() finally: shutil.rmtree(tmpdir)
def testOpSelectLabels(self): op = OpSelectLabels(graph=Graph()) small = numpy.asarray( [[0, 0, 0], [0, 1, 0], [0, 0, 0]]).astype(np.uint32) big = numpy.asarray( [[0, 1, 0], [1, 1, 1], [0, 1, 0]]).astype(np.uint32) small = vigra.taggedView(small[:,:,None], 'yxc') big = vigra.taggedView(big[:,:,None], 'yxc') op.BigLabels.setValue(big) op.SmallLabels.setValue(small) out = op.Output[...].wait() numpy.testing.assert_array_equal(out, big) op.BigLabels.setValue(big) op.SmallLabels.setValue(small*0) out = op.Output[...].wait() numpy.testing.assert_array_equal(out, big*0)
def test_lzw_compressed_file(self): """ This test is loosely related to https://github.com/ilastik/ilastik/issues/1415 Tests whether lzw compressed tiff files can be read. """ import os basepath = os.path.split(__file__)[0] compressed_tiff_file = '{}/data/inputdata/compressed_lzw.tiff'.format( basepath) # generate checker-board, as in the file data = numpy.zeros((10, 20, 3)).astype(numpy.uint8) for i in range(data.shape[0]): if i % 2 == 0: data[i, 1::2, :] = 255 else: data[i, 0::2, :] = 255 op = OpTiffReader(graph=Graph()) op.Filepath.setValue(compressed_tiff_file) assert op.Output.ready() assert op.Output.meta.shape == data.shape assert_array_equal(data, op.Output[:].wait())
def testReconnectWithoutRequest(self): vol = numpy.zeros((200, 100, 50), dtype=numpy.float32) vol1 = vigra.taggedView(vol, axistags='xyz') vol2 = vigra.taggedView(vol, axistags='zyx').withAxes(*'xyz') graph = Graph() opData1 = OpArrayPiper(graph=graph) opData1.Input.setValue(vol1) op = OpCompressedCache(graph=graph) op.Input.connect(opData1.Output) op.BlockShape.setValue((200, 100, 10)) out = op.Output[...].wait().view(numpy.ndarray) assert (out == vol).all(), "Incorrect output!" op.BlockShape.setValue((50, 100, 10)) # Older versions of OpCompressedCache threw an exception here because # we tried to access the cache after changing the blockshape. # But in the current version, we claim that's okay. out = op.Output[...].wait() assert (out == vol).all(), "Incorrect output!"
def testCleanup(self): try: CacheMemoryManager().disable() sampleData = numpy.indices((100, 200, 150), dtype=numpy.float32).sum(0) sampleData = vigra.taggedView(sampleData, axistags="xyz") graph = Graph() opData = OpArrayPiper(graph=graph) opData.Input.setValue(sampleData) op = OpCompressedCache(graph=graph) # logger.debug("Setting block shape...") op.BlockShape.setValue([100, 75, 50]) op.Input.connect(opData.Output) x = op.Output[...].wait() op.Input.disconnect() r = weakref.ref(op) del op gc.collect() assert r( ) is None, "OpBlockedArrayCache was not cleaned up correctly" finally: CacheMemoryManager().enable()
def testMargin(self): graph = Graph() vol = np.zeros((100, 110, 10), dtype=np.float32) # draw a big plus sign vol[50:70, :, :] = 1.0 vol[:, 60:80, :] = 1.0 vol = vigra.taggedView(vol, axistags='zyx').withAxes(*'tzyxc') labels = np.zeros((100, 110, 10), dtype=np.uint32) labels[45:75, 55:85, 3:4] = 1 labels = vigra.taggedView(labels, axistags='zyx').withAxes(*'tzyxc') op = OpObjectsSegment(graph=graph) piper = OpArrayPiper(graph=graph) piper.Input.setValue(vol) op.Prediction.connect(piper.Output) op.LabelImage.setValue(labels) # without margin op.MarginZYX.setValue(np.asarray((0, 0, 0))) out = op.Output[...].wait() out = vigra.taggedView(out, axistags=op.Output.meta.axistags) out = out.withAxes(*'zyx') vol = vol.withAxes(*'zyx') assert_array_equal(out[50:70, 60:80, 3] > 0, vol[50:70, 60:80, 3] > .5) assert np.all(out[:45, ...] == 0) # with margin op.MarginZYX.setValue(np.asarray((5, 5, 0))) out = op.Output[...].wait() out = vigra.taggedView(out, axistags=op.Output.meta.axistags) out = out.withAxes(*'zyx') assert_array_equal(out[45:75, 55:85, 3] > 0, vol[45:75, 55:85, 3] > .5) assert np.all(out[:40, ...] == 0)
def setUp(self): self.g = Graph() self.op = OpOuter(graph=self.g)
non_singleton_dims = filter(lambda (k, v): k != 'c' and v > 1, tagged_shape.items()) assert len(non_singleton_dims) <= 2, \ "Image to export must have no more than 2 non-singleton dimensions.\n"\ "You are attempting to export a {}D result into a 2D file format."\ .format( len(non_singleton_dims) ) data = self._opExportToArray.run_export_to_array() data = vigra.taggedView(data, self.Input.meta.axistags) data = data.squeeze() if len(data.shape) == 1 or len( data.shape) == 2 and data.axistags.channelIndex < 2: data = data[numpy.newaxis, :] assert len(data.shape) == 2 or (len(data.shape) == 3 and data.axistags.channelIndex < 3), \ "Image has shape {}, channelIndex is {}".format(data.shape, data.axistags.channelIndex) vigra.impex.writeImage(data, self.Filepath.value) if __name__ == "__main__": a = numpy.random.random((1, 100, 1, 100, 1)) * 255 a = a.astype(numpy.uint8) a = vigra.taggedView(a, vigra.defaultAxistags('txyzc')) from lazyflow.graph import Graph op = OpExport2DImage(graph=Graph()) op.Input.setValue(a) op.Filepath.setValue('/tmp/test.png') op.run_export()
class TestSlot_notifyDisconnect(object): def setUp(self): self.g = Graph() def tearDown(self): self.g.stopGraph() def test_disconnect(self): # test that the notifyConnect callback is called # when the slot is connected ops = OpS(graph=self.g) opa = OpA(graph=self.g) upval = [False] def callBack(slot): upval[0] = True # check the disconnect callback is called upon disconnect opa.Input1.connect(ops.Output1) opa.Input1.notifyDisconnect(callBack) opa.Input1.disconnect() assert upval[0] == True # check the disconnect callback is called upon reconnect opa.Input1.connect(ops.Output1) upval[0] = False opa.Input1.connect(ops.Output2) assert upval[0] == True # check the disconnect callback is called upon setValue when being already connected opa.Input1.connect(ops.Output1) upval[0] = False opa.Input1.disconnect() opa.Input1.setValue(19) assert upval[0] == True def test_no_disconnect(self): ops = OpS(graph=self.g) opa = OpA(graph=self.g) upval = [False] def callBack(slot): upval[0] = True opa.Input1.notifyDisconnect(callBack) # check the disconnect callback is not called when reconnecting to the same slot opa.Input1.connect(ops.Output1) upval[0] = False opa.Input1.connect(ops.Output1) assert upval[0] == False # check the disconnect callback is not called when setting the same value again opa.Input1.disconnect() opa.Input1.setValue(10) upval[0] = False opa.Input1.setValue(10) assert upval[0] == False def test_unregister_disconnect(self): # check that unregistering a disconnect callback works ops = OpS(graph=self.g) opa = OpA(graph=self.g) upval = [False] def callBack(slot): upval[0] = True opa.Input1.connect(ops.Output1) opa.Input1.notifyDisconnect(callBack) opa.Input1.unregisterDisconnect(callBack) opa.Input1.disconnect() assert upval[0] == False
shape = tuple(self._slot.meta.shape) axes = "".join(self._slot.meta.getAxisKeys()) dtype = self._slot.meta.dtype.__name__ else: shape = axes = dtype = "" if not sip.isdeleted(self.shapeEdit): self.shapeEdit.setText(str(shape)) self.axisOrderEdit.setText(axes) self.dtypeEdit.setText(dtype) if __name__ == "__main__": import numpy import vigra from PyQt4.QtGui import QApplication from lazyflow.graph import Graph from lazyflow.operators import OpArrayCache data = numpy.zeros((10, 20, 30, 3), dtype=numpy.float32) data = vigra.taggedView(data, 'zyxc') op = OpArrayCache(graph=Graph()) op.Input.setValue(data) app = QApplication([]) w = SlotMetaInfoDisplayWidget(None) w.initSlot(op.Output) w.show() app.exec_()
# when the dot happen to be in the centre of the movable squere in the # image then we show a one on the top left corner # =========================================================================== from ilastik.widgets.boxListView import BoxListView from PyQt5.QtWidgets import QWidget app = QApplication([]) boxListModel = BoxListModel() h, w = (500, 500) LV = BoxListView() LV.setModel(boxListModel) LV._table.setShowGrid(True) g = Graph() cron = QTimer() cron.start(500 * 100) op = OpArrayPiper2(graph=g) # Generate random noise shape = (1, w, h, 1, 1) # array = np.random.randint(0,255,500*500).reshape(shape).astype(np.uint8) import scipy array = scipy.misc.lena().astype(np.uint8) array = vigra.sampling.resize(array.astype(np.float32), (h, w)).reshape(shape).astype(np.uint8) op.Input.setValue(array) def do():
def __init__( self, shell, headless, workflow_cmdline_args, project_creation_args, *args, **kwargs ): graph = kwargs['graph'] if 'graph' in kwargs else Graph() if 'graph' in kwargs: del kwargs['graph'] super(StructuredTrackingWorkflowBase, self).__init__(shell, headless, workflow_cmdline_args, project_creation_args, graph=graph, *args, **kwargs) data_instructions = 'Use the "Raw Data" tab to load your intensity image(s).\n\n' if self.fromBinary: data_instructions += 'Use the "Binary Image" tab to load your segmentation image(s).' else: data_instructions += 'Use the "Prediction Maps" tab to load your pixel-wise probability image(s).' # Create applets self.dataSelectionApplet = DataSelectionApplet(self, "Input Data", "Input Data", batchDataGui=False, forceAxisOrder=['txyzc'], instructionText=data_instructions, max_lanes=1) opDataSelection = self.dataSelectionApplet.topLevelOperator if self.fromBinary: opDataSelection.DatasetRoles.setValue( ['Raw Data', 'Binary Image'] ) else: opDataSelection.DatasetRoles.setValue( ['Raw Data', 'Prediction Maps'] ) if not self.fromBinary: self.thresholdTwoLevelsApplet = ThresholdTwoLevelsApplet( self,"Threshold and Size Filter","ThresholdTwoLevels" ) self.divisionDetectionApplet = ObjectClassificationApplet(workflow=self, name="Division Detection (optional)", projectFileGroupName="DivisionDetection", selectedFeatures=configConservation.selectedFeaturesDiv) self.cellClassificationApplet = ObjectClassificationApplet(workflow=self, name="Object Count Classification", projectFileGroupName="CountClassification", selectedFeatures=configConservation.selectedFeaturesObjectCount) self.trackingFeatureExtractionApplet = TrackingFeatureExtractionApplet(name="Object Feature Computation",workflow=self, interactive=False) self.objectExtractionApplet = ObjectExtractionApplet(name="Object Feature Computation",workflow=self, interactive=False) self.annotationsApplet = AnnotationsApplet( name="Training", workflow=self ) opAnnotations = self.annotationsApplet.topLevelOperator self.trackingApplet = StructuredTrackingApplet( name="Tracking - Structured Learning", workflow=self ) opStructuredTracking = self.trackingApplet.topLevelOperator if SOLVER=="CPLEX" or SOLVER=="GUROBI": self._solver="ILP" elif SOLVER=="DPCT": self._solver="Flow-based" else: self._solver=None opStructuredTracking._solver = self._solver self.default_tracking_export_filename = '{dataset_dir}/{nickname}-tracking_exported_data.csv' self.dataExportTrackingApplet = TrackingBaseDataExportApplet(self, "Tracking Result Export",default_export_filename=self.default_tracking_export_filename) opDataExportTracking = self.dataExportTrackingApplet.topLevelOperator opDataExportTracking.SelectionNames.setValue( ['Tracking-Result', 'Merger-Result', 'Object-Identities'] ) opDataExportTracking.WorkingDirectory.connect( opDataSelection.WorkingDirectory ) self.dataExportTrackingApplet.set_exporting_operator(opStructuredTracking) self.dataExportTrackingApplet.prepare_lane_for_export = self.prepare_lane_for_export self.dataExportTrackingApplet.post_process_lane_export = self.post_process_lane_export # configure export settings settings = {'file path': self.default_tracking_export_filename, 'compression': {}, 'file type': 'h5'} selected_features = ['Count', 'RegionCenter', 'RegionRadii', 'RegionAxes'] opStructuredTracking.ExportSettings.setValue( (settings, selected_features) ) self._applets = [] self._applets.append(self.dataSelectionApplet) if not self.fromBinary: self._applets.append(self.thresholdTwoLevelsApplet) self._applets.append(self.trackingFeatureExtractionApplet) self._applets.append(self.divisionDetectionApplet) self.batchProcessingApplet = BatchProcessingApplet(self, "Batch Processing", self.dataSelectionApplet, self.dataExportTrackingApplet) self._applets.append(self.cellClassificationApplet) self._applets.append(self.objectExtractionApplet) self._applets.append(self.annotationsApplet) self._applets.append(self.trackingApplet) self._applets.append(self.dataExportTrackingApplet) if self.divisionDetectionApplet: opDivDetection = self.divisionDetectionApplet.topLevelOperator opDivDetection.SelectedFeatures.setValue(configConservation.selectedFeaturesDiv) opDivDetection.LabelNames.setValue(['Not Dividing', 'Dividing']) opDivDetection.AllowDeleteLabels.setValue(False) opDivDetection.AllowAddLabel.setValue(False) opDivDetection.EnableLabelTransfer.setValue(False) opCellClassification = self.cellClassificationApplet.topLevelOperator opCellClassification.SelectedFeatures.setValue(configConservation.selectedFeaturesObjectCount ) opCellClassification.SuggestedLabelNames.setValue( ['False Detection',] + [str(1) + ' Object'] + [str(i) + ' Objects' for i in range(2,10) ] ) opCellClassification.AllowDeleteLastLabelOnly.setValue(True) opCellClassification.EnableLabelTransfer.setValue(False) if workflow_cmdline_args: if '--testFullAnnotations' in workflow_cmdline_args: self.testFullAnnotations = True else: self.testFullAnnotations = False self._data_export_args, unused_args = self.dataExportTrackingApplet.parse_known_cmdline_args( workflow_cmdline_args ) self._batch_input_args, unused_args = self.batchProcessingApplet.parse_known_cmdline_args( workflow_cmdline_args ) else: unused_args = None self._data_export_args = None self._batch_input_args = None self.testFullAnnotations = False if unused_args: logger.warning("Unused command-line args: {}".format( unused_args ))
def __init__(self, shell, headless, workflow_cmdline_args, project_creation_args, *args, **kwargs): # Create a graph to be shared by all operators graph = Graph() super(NNClassificationWorkflow, self).__init__(shell, headless, workflow_cmdline_args, project_creation_args, graph=graph, *args, **kwargs) self._applets = [] self._workflow_cmdline_args = workflow_cmdline_args # Parse workflow-specific command-line args parser = argparse.ArgumentParser() # parser.add_argument('--print-labels-by-slice', help="Print the number of labels for each Z-slice of each image.", action="store_true") # Parse the creation args: These were saved to the project file when this project was first created. parsed_creation_args, unused_args = parser.parse_known_args( project_creation_args) # Parse the cmdline args for the current session. parsed_args, unused_args = parser.parse_known_args( workflow_cmdline_args) # self.print_labels_by_slice = parsed_args.print_labels_by_slice data_instructions = ( "Select your input data using the 'Raw Data' tab shown on the right.\n\n" "Power users: Optionally use the 'Prediction Mask' tab to supply a binary image that tells ilastik where it should avoid computations you don't need." ) # Applets for training (interactive) workflow self.dataSelectionApplet = self.createDataSelectionApplet() opDataSelection = self.dataSelectionApplet.topLevelOperator # see role constants, above opDataSelection.DatasetRoles.setValue( NNClassificationWorkflow.ROLE_NAMES) self.nnClassificationApplet = NNClassApplet(self, "NNClassApplet") self.dataExportApplet = NNClassificationDataExportApplet( self, "Data Export") # Configure global DataExport settings opDataExport = self.dataExportApplet.topLevelOperator opDataExport.WorkingDirectory.connect(opDataSelection.WorkingDirectory) opDataExport.SelectionNames.setValue(self.EXPORT_NAMES) self.batchProcessingApplet = BatchProcessingApplet( self, "Batch Processing", self.dataSelectionApplet, self.dataExportApplet) # Expose for shell self._applets.append(self.dataSelectionApplet) self._applets.append(self.nnClassificationApplet) self._applets.append(self.dataExportApplet) self._applets.append(self.batchProcessingApplet) if unused_args: # We parse the export setting args first. All remaining args are considered input files by the input applet. self._batch_export_args, unused_args = self.dataExportApplet.parse_known_cmdline_args( unused_args) self._batch_input_args, unused_args = self.batchProcessingApplet.parse_known_cmdline_args( unused_args) else: self._batch_input_args = None self._batch_export_args = None if unused_args: logger.warn("Unused command-line args: {}".format(unused_args))
self.progressSignal(100) def propagateDirty(self, slot, subindex, roi): # The output from this operator isn't generally connected to other operators. # If someone is using it that way, we'll assume that the user wants to know that # the input image has become dirty and may need to be written to disk again. self.WriteImage.setDirty(slice(None)) if __name__ == "__main__": from lazyflow.graph import Graph import h5py import sys traceLogger.addHandler(logging.StreamHandler(sys.stdout)) traceLogger.setLevel(logging.DEBUG) traceLogger.debug("HELLO") f = h5py.File("/tmp/flyem_sample_stack.h5", "r") internalPath = "volume/data" # OpStackToH5Writer graph = Graph() opStackToH5 = OpStackToH5Writer() opStackToH5.GlobString.setValue("/tmp/flyem_sample_stack/*.png") opStackToH5.hdf5Group.setValue(f) opStackToH5.hdf5Path.setValue(internalPath) success = opStackToH5.WriteImage.value assert success
def generate_trained_project_file(new_project_path, raw_data_paths, label_data_paths, feature_selections, classifier_factory=None): """ Create a new project file from scratch, add the given raw data files, inject the corresponding labels, configure the given feature selections, and (if provided) override the classifier type ('factory'). Finally, request the classifier object from the pipeline (which forces training), and save the project. new_project_path: Where to save the new project file raw_data_paths: A list of paths to the raw data images to train with label_data_paths: A list of paths to the label image data to train with feature_selections: A matrix of bool, representing the selected features classifier_factory: Override the classifier type. Must be a subclass of either: - lazyflow.classifiers.LazyflowVectorwiseClassifierFactoryABC - lazyflow.classifiers.LazyflowPixelwiseClassifierFactoryABC """ assert len(raw_data_paths) == len( label_data_paths ), "Number of label images must match number of raw images." import ilastik_main from ilastik.workflows.pixelClassification import PixelClassificationWorkflow from lazyflow.graph import Graph from lazyflow.operators.ioOperators import OpInputDataReader from lazyflow.roi import roiToSlice, roiFromShape ## ## CREATE PROJECT ## # Manually configure the arguments to ilastik, as if they were parsed from the command line. # (Start with empty args and fill in below.) ilastik_args = ilastik_main.parse_args([]) ilastik_args.new_project = new_project_path ilastik_args.headless = True ilastik_args.workflow = "Pixel Classification" shell = ilastik_main.main(ilastik_args) assert isinstance(shell.workflow, PixelClassificationWorkflow) ## ## CONFIGURE GRAYSCALE INPUT ## data_selection_applet = shell.workflow.dataSelectionApplet # To configure data selection, start with empty cmdline args and manually fill them in data_selection_args, _ = data_selection_applet.parse_known_cmdline_args( [], PixelClassificationWorkflow.ROLE_NAMES) data_selection_args.raw_data = raw_data_paths data_selection_args.preconvert_stacks = True # Simplest thing here is to configure using cmd-line interface data_selection_applet.configure_operator_with_parsed_args( data_selection_args) ## ## APPLY FEATURE MATRIX (from matrix above) ## opFeatures = shell.workflow.featureSelectionApplet.topLevelOperator opFeatures.Scales.setValue(ScalesList) opFeatures.FeatureIds.setValue(FeatureIds) opFeatures.SelectionMatrix.setValue(feature_selections) ## ## CUSTOMIZE CLASSIFIER TYPE ## opPixelClassification = shell.workflow.pcApplet.topLevelOperator if classifier_factory is not None: opPixelClassification.ClassifierFactory.setValue(classifier_factory) ## ## READ/APPLY LABEL VOLUMES ## # Read each label volume and inject the label data into the appropriate training slot cwd = os.getcwd() max_label_class = 0 for lane, label_data_path in enumerate(label_data_paths): graph = Graph() opReader = OpInputDataReader(graph=graph) try: opReader.WorkingDirectory.setValue(cwd) opReader.FilePath.setValue(label_data_path) print("Reading label volume: {}".format(label_data_path)) label_volume = opReader.Output[:].wait() finally: opReader.cleanUp() raw_shape = opPixelClassification.InputImages[lane].meta.shape if label_volume.ndim != len(raw_shape): # Append a singleton channel axis assert label_volume.ndim == len(raw_shape) - 1 label_volume = label_volume[..., None] # Auto-calculate the max label value max_label_class = max(max_label_class, label_volume.max()) print("Applying label volume to lane #{}".format(lane)) entire_volume_slicing = roiToSlice(*roiFromShape(label_volume.shape)) opPixelClassification.LabelInputs[lane][ entire_volume_slicing] = label_volume assert max_label_class > 1, "Not enough label classes were found in your label data." label_names = list(map(str, list(range(max_label_class)))) opPixelClassification.LabelNames.setValue(label_names) ## ## TRAIN CLASSIFIER ## # Make sure the caches in the pipeline are not 'frozen'. # (This is the equivalent of 'live update' mode in the GUI.) opPixelClassification.FreezePredictions.setValue(False) # Request the classifier object from the pipeline. # This forces the pipeline to produce (train) the classifier. _ = opPixelClassification.Classifier.value ## ## SAVE PROJECT ## # save project file (includes the new classifier). shell.projectManager.saveProject(force_all_save=False)
class TestSlot_notifyConnect(object): def setUp(self): self.g = Graph() def tearDown(self): self.g.stopGraph() def test_connect(self): # test that the notifyConnect callback is called # when the slot is connected ops = OpS(graph=self.g) opa = OpA(graph=self.g) opa.Input2.connect(ops.Output2) upval = [False] def callBack(slot): upval[0] = True # check the connect callback is called opa.Input1._notifyConnect(callBack) opa.Input1.connect(ops.Output1) assert upval[0] == True # check the connect callback is called for a slot with default value upval[0] = False opa.Input3._notifyConnect(callBack) opa.Input3.connect(ops.Output3) assert upval[0] == True # check the connect callback is called for a multi inputslot upval[0] = False opa.Input4._notifyConnect(callBack) opa.Input4.connect(ops.Output4) assert upval[0] == True def test_no_connect(self): ops = OpS(graph=self.g) opa = OpA(graph=self.g) upval = [False] def callBack(slot): upval[0] = True opa.Input1._notifyConnect(callBack) # check the connect callback is not called when reconnecting to the same slot opa.Input1.connect(ops.Output1) upval[0] = False opa.Input1.connect(ops.Output1) assert upval[0] == False # check the connect callback is not called when setting the same value again opa.Input1.disconnect() opa.Input1.setValue(10) upval[0] = False opa.Input1.setValue(10) assert upval[0] == False def test_unregister_connect(self): # check that unregistering a connect callback works ops = OpS(graph=self.g) opa = OpA(graph=self.g) upval = [False] def callBack(slot): upval[0] = True opa.Input1._notifyConnect(callBack) opa.Input1._unregisterConnect(callBack) opa.Input1.connect(ops.Output1) assert upval[0] == False
class Main(QMainWindow): haveData = pyqtSignal() dataReadyToView = pyqtSignal() def __init__(self, argv): QMainWindow.__init__(self) #Normalize the data if true self._normalize_data=True if 'notnormalize' in sys.argv: print sys.argv self._normalize_data=False sys.argv.remove('notnormalize') self.opPredict = None self.opTrain = None self.opThreshold = None self._colorTable16 = self._createDefault16ColorColorTable() #self.g = Graph(7, 2048*1024**2*5) self.g = Graph() self.fixableOperators = [] self.featureDlg=None #The old ilastik provided the following scale names: #['Tiny', 'Small', 'Medium', 'Large', 'Huge', 'Megahuge', 'Gigahuge'] #The corresponding scales are: self.featScalesList=[0.3, 0.7, 1, 1.6, 3.5, 5.0, 10.0] self.initUic() #if the filename was specified on command line, load it if len(sys.argv) >= 2: def loadFile(): self._openFile(sys.argv[1:]) QTimer.singleShot(0, loadFile) def setIconToViewMenu(self): self.actionOnly_for_current_view.setIcon(QIcon(self.editor.imageViews[self.editor._lastImageViewFocus]._hud.axisLabel.pixmap())) def initUic(self): p = os.path.split(__file__)[0]+'/' if p == "/": p = "."+p uic.loadUi(p+"MainWindow_cc.ui", self) #connect the window and graph creation to the opening of the file self.actionOpen.triggered.connect(self.openFile) self.actionQuit.triggered.connect(qApp.quit) def toggleDebugPatches(show): self.editor.showDebugPatches = show def fitToScreen(): shape = self.editor.posModel.shape for i, v in enumerate(self.editor.imageViews): s = list(copy.copy(shape)) del s[i] v.changeViewPort(v.scene().data2scene.mapRect(QRectF(0,0,*s))) def fitImage(): if hasattr(self.editor, '_lastImageViewFocus'): self.editor.imageViews[self.editor._lastImageViewFocus].fitImage() def restoreImageToOriginalSize(): if hasattr(self.editor, '_lastImageViewFocus'): self.editor.imageViews[self.editor._lastImageViewFocus].doScaleTo() def rubberBandZoom(): if hasattr(self.editor, '_lastImageViewFocus'): if not self.editor.imageViews[self.editor._lastImageViewFocus]._isRubberBandZoom: self.editor.imageViews[self.editor._lastImageViewFocus]._isRubberBandZoom = True self.editor.imageViews[self.editor._lastImageViewFocus]._cursorBackup = self.editor.imageViews[self.editor._lastImageViewFocus].cursor() self.editor.imageViews[self.editor._lastImageViewFocus].setCursor(Qt.CrossCursor) else: self.editor.imageViews[self.editor._lastImageViewFocus]._isRubberBandZoom = False self.editor.imageViews[self.editor._lastImageViewFocus].setCursor(self.editor.imageViews[self.editor._lastImageViewFocus]._cursorBackup) def hideHud(): if self.editor.imageViews[0]._hud.isVisible(): hide = False else: hide = True for i, v in enumerate(self.editor.imageViews): v.hideHud(hide) def toggleSelectedHud(): if hasattr(self.editor, '_lastImageViewFocus'): self.editor.imageViews[self.editor._lastImageViewFocus].toggleHud() def centerAllImages(): for i, v in enumerate(self.editor.imageViews): v.centerImage() def centerImage(): if hasattr(self.editor, '_lastImageViewFocus'): self.editor.imageViews[self.editor._lastImageViewFocus].centerImage() self.actionOnly_for_current_view.setEnabled(True) self.actionCenterAllImages.triggered.connect(centerAllImages) self.actionCenterImage.triggered.connect(centerImage) self.actionToggleAllHuds.triggered.connect(hideHud) self.actionToggleSelectedHud.triggered.connect(toggleSelectedHud) self.actionShowDebugPatches.toggled.connect(toggleDebugPatches) self.actionFitToScreen.triggered.connect(fitToScreen) self.actionFitImage.triggered.connect(fitImage) self.actionReset_zoom.triggered.connect(restoreImageToOriginalSize) self.actionRubberBandZoom.triggered.connect(rubberBandZoom) self.haveData.connect(self.initGraph) self.dataReadyToView.connect(self.initEditor) self.layerstack = LayerStackModel() model = LabelListModel() self.labelListView.setModel(model) self.labelListModel=model self.labelListModel.rowsAboutToBeRemoved.connect(self.onLabelAboutToBeRemoved) self.labelListModel.labelSelected.connect(self.switchLabel) def onDataChanged(topLeft, bottomRight): firstRow = topLeft.row() lastRow = bottomRight.row() firstCol = topLeft.column() lastCol = bottomRight.column() if lastCol == firstCol == 0: assert(firstRow == lastRow) #only one data item changes at a time #in this case, the actual data (for example color) has changed self.switchColor(firstRow+1, self.labelListModel[firstRow].color) self.editor.scheduleSlicesRedraw() else: #this column is used for the 'delete' buttons, we don't care #about data changed here pass self.labelListModel.dataChanged.connect(onDataChanged) self.AddLabelButton.clicked.connect(self.addLabel) self.SelectFeaturesButton.clicked.connect(self.onFeatureButtonClicked) self.StartClassificationButton.clicked.connect(self.startClassification) self.StartClassificationButton.setEnabled(False) self.checkInteractive.setEnabled(False) self.checkInteractive.toggled.connect(self.toggleInteractive) self.interactionComboBox.currentIndexChanged.connect(self.changeInteractionMode) self.interactionComboBox.setEnabled(False) self.AddThresholdButton.clicked.connect(self.addThresholdOperator) self.AddThresholdButton.setEnabled(False) self.CCButton.clicked.connect(self.addCCOperator) self.CCButton.setEnabled(False) self._initFeatureDlg() def toggleInteractive(self, checked): print "toggling interactive mode to '%r'" % checked #Check if the number of labels in the layer stack is equals to the number of Painted labels if checked==True: labels =numpy.unique(numpy.asarray(self.opLabels.outputs["nonzeroValues"][:].allocate().wait()[0])) nPaintedLabels=labels.shape[0] nLabelsLayers = self.labelListModel.rowCount() selectedFeatures = numpy.asarray(self.featureDlg.featureTableWidget.createSelectedFeaturesBoolMatrix()) if nPaintedLabels!=nLabelsLayers: self.checkInteractive.setCheckState(0) mexBox=QMessageBox() mexBox.setText("Did you forget to paint some labels?") mexBox.setInformativeText("Painted Labels %d \nNumber Active Labels Layers %d"%(nPaintedLabels,self.labelListModel.rowCount())) mexBox.exec_() return if (selectedFeatures==0).all(): self.checkInteractive.setCheckState(0) mexBox=QMessageBox() mexBox.setText("The are no features selected ") mexBox.exec_() return else: self.g.stopGraph() self.g.resumeGraph() self.AddLabelButton.setEnabled(not checked) self.SelectFeaturesButton.setEnabled(not checked) for o in self.fixableOperators: o.inputs["fixAtCurrent"].setValue(not checked) self.labelListModel.allowRemove(not checked) self.editor.scheduleSlicesRedraw() def changeInteractionMode( self, index ): modes = {0: "navigation", 1: "brushing"} self.editor.setInteractionMode( modes[index] ) self.interactionComboBox.setCurrentIndex(index) print "interaction mode switched to", modes[index] def switchLabel(self, row): print "switching to label=%r" % (self.labelListModel[row]) #+1 because first is transparent #FIXME: shouldn't be just row+1 here self.editor.brushingModel.setDrawnNumber(row+1) self.editor.brushingModel.setBrushColor(self.labelListModel[row].color) def switchColor(self, row, color): print "label=%d changes color to %r" % (row, color) self.labellayer.colorTable[row]=color.rgba() self.editor.brushingModel.setBrushColor(color) self.editor.scheduleSlicesRedraw() def addLabel(self): color = QColor(numpy.random.randint(0,255), numpy.random.randint(0,255), numpy.random.randint(0,255)) numLabels = len(self.labelListModel) if numLabels < len(self._colorTable16): color = self._colorTable16[numLabels] self.labellayer.colorTable.append(color.rgba()) self.labelListModel.insertRow(self.labelListModel.rowCount(), Label("Label %d" % (self.labelListModel.rowCount() + 1), color)) nlabels = self.labelListModel.rowCount() if self.opPredict is not None: print "Label added, changing predictions" #re-train the forest now that we have more labels self.opPredict.inputs['LabelsCount'].setValue(nlabels) self.addPredictionLayer(nlabels-1, self.labelListModel._labels[nlabels-1]) #make the new label selected index = self.labelListModel.index(nlabels-1, 1) self.labelListModel._selectionModel.select(index, QItemSelectionModel.ClearAndSelect) #FIXME: this should watch for model changes #drawing will be enabled when the first label is added self.changeInteractionMode( 1 ) self.interactionComboBox.setEnabled(True) def onLabelAboutToBeRemoved(self, parent, start, end): #the user deleted a label, reshape prediction and remove the layer #the interface only allows to remove one label at a time? nout = start-end+1 ncurrent = self.labelListModel.rowCount() print "removing", nout, "out of ", ncurrent if self.opPredict is not None: self.opPredict.inputs['LabelsCount'].setValue(ncurrent-nout) for il in range(start, end+1): labelvalue = self.labelListModel._labels[il] self.removePredictionLayer(labelvalue) self.opLabels.inputs["deleteLabel"].setValue(il+1) self.editor.scheduleSlicesRedraw() def startClassification(self): if self.opTrain is None: #initialize all classification operators print "initializing classification..." opMultiL = Op5ToMulti(self.g) opMultiL.inputs["Input0"].connect(self.opLabels.outputs["Output"]) opMultiLblocks = Op5ToMulti(self.g) opMultiLblocks.inputs["Input0"].connect(self.opLabels.outputs["nonzeroBlocks"]) self.opTrain = OpTrainRandomForestBlocked(self.g) self.opTrain.inputs['Labels'].connect(opMultiL.outputs["Outputs"]) self.opTrain.inputs['Images'].connect(self.opFeatureCache.outputs["Output"]) self.opTrain.inputs["nonzeroLabelBlocks"].connect(opMultiLblocks.outputs["Outputs"]) self.opTrain.inputs['fixClassifier'].setValue(False) opClassifierCache = OpArrayCache(self.g) opClassifierCache.inputs["Input"].connect(self.opTrain.outputs['Classifier']) ################## Prediction self.opPredict=OpPredictRandomForest(self.g) nclasses = self.labelListModel.rowCount() self.opPredict.inputs['LabelsCount'].setValue(nclasses) self.opPredict.inputs['Classifier'].connect(opClassifierCache.outputs['Output']) self.opPredict.inputs['Image'].connect(self.opPF.outputs["Output"]) pCache = OpSlicedBlockedArrayCache(self.g) pCache.inputs["fixAtCurrent"].setValue(False) pCache.inputs["innerBlockShape"].setValue(((1,256,256,1,2),(1,256,1,256,2),(1,1,256,256,2))) pCache.inputs["outerBlockShape"].setValue(((1,256,256,4,2),(1,256,4,256,2),(1,4,256,256,2))) pCache.inputs["Input"].connect(self.opPredict.outputs["PMaps"]) self.pCache = pCache #add prediction results for all classes as separate channels for icl in range(nclasses): self.addPredictionLayer(icl, self.labelListModel._labels[icl]) self.StartClassificationButton.setEnabled(False) self.checkInteractive.setEnabled(True) self.AddThresholdButton.setEnabled(True) def addPredictionLayer(self, icl, ref_label): selector=OpSingleChannelSelector(self.g) selector.inputs["Input"].connect(self.pCache.outputs['Output']) selector.inputs["Index"].setValue(icl) if self.checkInteractive.isChecked(): self.pCache.inputs["fixAtCurrent"].setValue(False) else: self.pCache.inputs["fixAtCurrent"].setValue(True) predictsrc = LazyflowSource(selector.outputs["Output"][0]) def srcName(newName): predictsrc.setObjectName("Prediction for %s" % ref_label.name) srcName("") predictLayer = AlphaModulatedLayer(predictsrc, tintColor=ref_label.color) predictLayer.nameChanged.connect(srcName) def setLayerColor(c): print "as the color of label '%s' has changed, setting layer's '%s' tint color to %r" % (ref_label.name, predictLayer.name, c) predictLayer.tintColor = c ref_label.colorChanged.connect(setLayerColor) def setLayerName(n): newName = "Prediction for %s" % ref_label.name print "as the name of label '%s' has changed, setting layer's '%s' name to '%s'" % (ref_label.name, predictLayer.name, newName) predictLayer.name = newName setLayerName(ref_label.name) ref_label.nameChanged.connect(setLayerName) predictLayer.ref_object = ref_label #make sure that labels (index = 0) stay on top! self.layerstack.insert(1, predictLayer ) self.fixableOperators.append(self.pCache) def removePredictionLayer(self, ref_label): for il, layer in enumerate(self.layerstack): if layer.ref_object==ref_label: print "found the prediction", layer.ref_object, ref_label self.layerstack.removeRows(il, 1) break def addThresholdOperator(self): if self.opThreshold is None: self.opThreshold = OpThreshold(self.g) self.opThreshold.inputs["Input"].connect(self.pCache.outputs["Output"]) #channel, value = ThresholdDlg(self.labelListModel._labels) channel = 0 value = 0.5 ref_label = self.labelListModel._labels[channel] self.opThreshold.inputs["Channel"].setValue(channel) self.opThreshold.inputs["Threshold"].setValue(value) threshsrc = LazyflowSource(self.opThreshold.outputs["Output"][0]) threshsrc.setObjectName("Threshold for %s" % ref_label.name) transparent = QColor(0,0,0,0) white = QColor(255,255,255) colorTable = [transparent.rgba(), white.rgba()] threshLayer = ColortableLayer(threshsrc, colorTable = colorTable ) threshLayer.name = "Threshold for %s" % ref_label.name self.layerstack.insert(1, threshLayer) self.CCButton.setEnabled(True) def addCCOperator(self): self.opCC = OpConnectedComponents(self.g) self.opCC.inputs["Input"].connect(self.opThreshold.outputs["Output"]) #we shouldn't have to define these. But just in case... self.opCC.inputs["Neighborhood"].setValue(6) self.opCC.inputs["Background"].setValue(0) ccsrc = LazyflowSource(self.opCC.outputs["Output"][0]) ccsrc.setObjectName("Connected Components") ctb = colortables.create_default_16bit() ctb.insert(0, QColor(0, 0, 0, 0).rgba()) # make background transparent ccLayer = ColortableLayer(ccsrc, ctb) ccLayer.name = "Connected Components" self.layerstack.insert(1, ccLayer) def openFile(self): fileNames = QFileDialog.getOpenFileNames(self, "Open Image", os.path.abspath(__file__), "Numpy and h5 files (*.npy *.h5)") if fileNames.count() == 0: return self._openFile(fileNames) def _openFile(self, fileNames): self.inputProvider = None fName, fExt = os.path.splitext(str(fileNames[0])) print "Opening Files %r" % fileNames if fExt=='.npy': fileName = fileNames[0] if len(fileNames)>1: print "WARNING: only the first file will be read, multiple file prediction not supported yet" fName, fExt = os.path.splitext(str(fileName)) self.raw = numpy.load(str(fileName)) self.min, self.max = numpy.min(self.raw), numpy.max(self.raw) self.inputProvider = OpArrayPiper(self.g) self.raw = self.raw.view(vigra.VigraArray) self.raw.axistags = vigra.AxisTags( vigra.AxisInfo('t',vigra.AxisType.Time), vigra.AxisInfo('x',vigra.AxisType.Space), vigra.AxisInfo('y',vigra.AxisType.Space), vigra.AxisInfo('z',vigra.AxisType.Space), vigra.AxisInfo('c',vigra.AxisType.Channels)) self.inputProvider.inputs["Input"].setValue(self.raw) elif fExt=='.h5': readerNew=OpH5ReaderBigDataset(self.g) readerNew.inputs["Filenames"].setValue(fileNames) readerNew.inputs["hdf5Path"].setValue("volume/data") readerCache = OpSlicedBlockedArrayCache(self.g) readerCache.inputs["fixAtCurrent"].setValue(False) readerCache.inputs["innerBlockShape"].setValue(((1,256,256,1,2),(1,256,1,256,2),(1,1,256,256,2))) readerCache.inputs["outerBlockShape"].setValue(((1,256,256,4,2),(1,256,4,256,2),(1,4,256,256,2))) readerCache.inputs["Input"].connect(readerNew.outputs["Output"]) self.inputProvider = OpArrayPiper(self.g) self.inputProvider.inputs["Input"].connect(readerCache.outputs["Output"]) else: raise RuntimeError("opening filenames=%r not supported yet" % fileNames) self.haveData.emit() def initGraph(self): shape = self.inputProvider.outputs["Output"].shape srcs = [] minMax = [] normalize = [] print "* Data has shape=%r" % (shape,) #create a layer for each channel of the input: slicer=OpMultiArraySlicer2(self.g) slicer.inputs["Input"].connect(self.inputProvider.outputs["Output"]) slicer.inputs["AxisFlag"].setValue('c') nchannels = shape[-1] for ich in xrange(nchannels): data=slicer.outputs['Slices'][ich][:].allocate().wait() #find the minimum and maximum value for normalization mm = (numpy.min(data), numpy.max(data)) print " - channel %d: min=%r, max=%r" % (ich, mm[0], mm[1]) minMax.append(mm) if self._normalize_data: normalize.append(mm) else: normalize.append((0,255)) layersrc = LazyflowSource(slicer.outputs['Slices'][ich], priority = 100) layersrc.setObjectName("raw data channel=%d" % ich) srcs.append(layersrc) #FIXME: we shouldn't merge channels automatically, but for now it's prettier layer1 = None if nchannels == 1: layer1 = GrayscaleLayer(srcs[0], range=minMax[0], normalize=normalize[0]) print " - showing raw data as grayscale" elif nchannels==2: layer1 = RGBALayer(red = srcs[0], normalizeR=normalize[0], green = srcs[1], normalizeG=normalize[1], range=minMax[0:2]+[(0,255), (0,255)]) print " - showing channel 1 as red, channel 2 as green" elif nchannels==3: layer1 = RGBALayer(red = srcs[0], normalizeR=normalize[0], green = srcs[1], normalizeG=normalize[1], blue = srcs[2], normalizeB=normalize[2], range = minMax[0:3]) print " - showing channel 1 as red, channel 2 as green, channel 3 as blue" else: print "only 1,2 or 3 channels supported so far" return print layer1.name = "Input data" layer1.ref_object = None self.layerstack.append(layer1) opImageList = Op5ToMulti(self.g) opImageList.inputs["Input0"].connect(self.inputProvider.outputs["Output"]) #init the features operator opPF = OpPixelFeaturesPresmoothed(self.g) opPF.inputs["Input"].connect(opImageList.outputs["Outputs"]) opPF.inputs["Scales"].setValue(self.featScalesList) self.opPF=opPF #Caches the features opFeatureCache = OpBlockedArrayCache(self.g) opFeatureCache.inputs["innerBlockShape"].setValue((1,32,32,32,16)) opFeatureCache.inputs["outerBlockShape"].setValue((1,128,128,128,64)) opFeatureCache.inputs["Input"].connect(opPF.outputs["Output"]) opFeatureCache.inputs["fixAtCurrent"].setValue(False) self.opFeatureCache=opFeatureCache self.initLabels() self.dataReadyToView.emit() def initLabels(self): #Add the layer to draw the labels, but don't add any labels shape=self.inputProvider.outputs["Output"].shape self.opLabels = OpBlockedSparseLabelArray(self.g) self.opLabels.inputs["shape"].setValue(shape[:-1] + (1,)) self.opLabels.inputs["blockShape"].setValue((1, 32, 32, 32, 1)) self.opLabels.inputs["eraser"].setValue(100) self.labelsrc = LazyflowSinkSource(self.opLabels, self.opLabels.outputs["Output"], self.opLabels.inputs["Input"]) self.labelsrc.setObjectName("labels") transparent = QColor(0,0,0,0) self.labellayer = ColortableLayer(self.labelsrc, colorTable = [transparent.rgba()] ) self.labellayer.name = "Labels" self.labellayer.ref_object = None self.layerstack.append(self.labellayer) def initEditor(self): shape=self.inputProvider.outputs["Output"].shape self.editor = VolumeEditor(self.layerstack, labelsink=self.labelsrc) self.editor.dataShape = shape self.editor.newImageView2DFocus.connect(self.setIconToViewMenu) #drawing will be enabled when the first label is added self.editor.setInteractionMode( 'navigation' ) self.volumeEditorWidget.init(self.editor) model = self.editor.layerStack self.layerWidget.init(model) self.UpButton.clicked.connect(model.moveSelectedUp) model.canMoveSelectedUp.connect(self.UpButton.setEnabled) self.DownButton.clicked.connect(model.moveSelectedDown) model.canMoveSelectedDown.connect(self.DownButton.setEnabled) self.DeleteButton.clicked.connect(model.deleteSelected) model.canDeleteSelected.connect(self.DeleteButton.setEnabled) self.opLabels.inputs["eraser"].setValue(self.editor.brushingModel.erasingNumber) def _createDefault16ColorColorTable(self): c = [] c.append(QColor(0, 0, 255)) c.append(QColor(255, 255, 0)) c.append(QColor(255, 0, 0)) c.append(QColor(0, 255, 0)) c.append(QColor(0, 255, 255)) c.append(QColor(255, 0, 255)) c.append(QColor(255, 105, 180)) #hot pink c.append(QColor(102, 205, 170)) #dark aquamarine c.append(QColor(165, 42, 42)) #brown c.append(QColor(0, 0, 128)) #navy c.append(QColor(255, 165, 0)) #orange c.append(QColor(173, 255, 47)) #green-yellow c.append(QColor(128,0, 128)) #purple c.append(QColor(192, 192, 192)) #silver c.append(QColor(240, 230, 140)) #khaki c.append(QColor(69, 69, 69)) # dark grey return c def onFeatureButtonClicked(self): self.featureDlg.show() def onDlgAccepted(): self.StartClassificationButton.setEnabled(True) self.featureDlg.accepted.connect(onDlgAccepted) def _onFeaturesChosen(self): selectedFeatures = self.featureDlg.featureTableWidget.createSelectedFeaturesBoolMatrix() print "new feature set:", selectedFeatures self.opPF.inputs['Matrix'].setValue(numpy.asarray(selectedFeatures)) def _initFeatureDlg(self): dlg = self.featureDlg = FeatureDlg() dlg.setWindowTitle("Features") dlg.createFeatureTable({"Features": [FeatureEntry("Gaussian smoothing"), \ FeatureEntry("Laplacian of Gaussian"), \ FeatureEntry("Structure Tensor Eigenvalues"), \ FeatureEntry("Hessian of Gaussian EV"), \ FeatureEntry("Gaussian Gradient Magnitude"), \ FeatureEntry("Difference Of Gaussian")]}, \ self.featScalesList) dlg.setImageToPreView(None) m = [[1,0,0,0,0,0,0],[1,0,0,0,0,0,0],[0,0,0,0,0,0,0],[1,0,0,0,0,0,0],[1,0,0,0,0,0,0],[1,0,0,0,0,0,0]] dlg.featureTableWidget.setSelectedFeatureBoolMatrix(m) dlg.accepted.connect(self._onFeaturesChosen)
def testFullAllocate(): nx = 5 ny = 10 nz = 2 nc = 7 stack = vigra.VigraArray((nx, ny, nz, nc), axistags=vigra.defaultAxistags('xyzc')) stack[...] = numpy.random.rand(nx, ny, nz, nc) g = Graph() #assume that the slicer works slicerX = OpMultiArraySlicer(graph=g) slicerX.inputs["Input"].setValue(stack) slicerX.inputs["AxisFlag"].setValue('x') #insert the x dimension stackerX = OpMultiArrayStacker(graph=g) stackerX.inputs["AxisFlag"].setValue('x') stackerX.inputs["AxisIndex"].setValue(0) stackerX.inputs["Images"].connect(slicerX.outputs["Slices"]) newdata = stackerX.outputs["Output"][:].wait() assert_array_equal(newdata, stack.view(numpy.ndarray)) print "1st part ok................." #merge stuff that already has an x dimension stack2 = vigra.VigraArray((nx-1, ny, nz, nc), axistags=vigra.defaultAxistags('xyzc')) stack2[...] = numpy.random.rand(nx-1, ny, nz, nc) opMulti = Op5ToMulti(graph=g) opMulti.inputs["Input0"].setValue(stack) opMulti.inputs["Input1"].setValue(stack2) #print "OPMULTI: ", len(opMulti.outputs["Outputs"]) stackerX2 = OpMultiArrayStacker(graph=g) stackerX2.inputs["Images"].connect(opMulti.outputs["Outputs"]) stackerX2.inputs["AxisFlag"].setValue('x') stackerX2.inputs["AxisIndex"].setValue(0) #print "STACKER: ", stackerX2.outputs["Output"].meta.shape newdata = stackerX2.outputs["Output"][:].wait() bothstacks = numpy.concatenate((stack, stack2), axis=0) assert_array_equal(newdata, bothstacks.view(numpy.ndarray)) #print newdata.shape, bothstacks.shape print "2nd part ok................." #print "------------------------------------------------------------" #print "------------------------------------------------------------" #print "------------------------------------------------------------" ##### channel #assume that the slicer works slicerC = OpMultiArraySlicer(graph=g) slicerC.inputs["Input"].setValue(stack) slicerC.inputs["AxisFlag"].setValue('c') #insert the c dimension stackerC = OpMultiArrayStacker(graph=g) stackerC.inputs["AxisFlag"].setValue('c') stackerC.inputs["AxisIndex"].setValue(3) stackerC.inputs["Images"].connect(slicerC.outputs["Slices"]) newdata = stackerC.outputs["Output"][:].wait() assert_array_equal(newdata, stack.view(numpy.ndarray)) print "3rd part ok................." #print "STACKER: ", stackerC.outputs["Output"].meta.shape #merge stuff that already has an x dimension stack3 = vigra.VigraArray((nx, ny, nz, nc-1), axistags=vigra.defaultAxistags('xyzc')) stack3[...] = numpy.random.rand(nx, ny, nz, nc-1) opMulti = Op5ToMulti(graph=g) opMulti.inputs["Input0"].setValue(stack) opMulti.inputs["Input1"].setValue(stack3) stackerC2 = OpMultiArrayStacker(graph=g) stackerC2.inputs["AxisFlag"].setValue('c') stackerC2.inputs["AxisIndex"].setValue(3) stackerC2.inputs["Images"].connect(opMulti.outputs["Outputs"]) newdata = stackerC2.outputs["Output"][:].wait() bothstacks = numpy.concatenate((stack, stack3), axis=3) assert_array_equal(newdata, bothstacks.view(numpy.ndarray)) print "4th part ok................." g.finalize()
def setUp(self): self.g = Graph() self.op = OpA(graph=self.g)
def setUp(self): self.g = Graph()