Beispiel #1
0
    def test_basic(self):
        opData = OpArrayCache(graph=self.graph)
        opData.blockShape.setValue(self.testData.shape)
        opData.Input.setValue(self.testData)

        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 = OpInputDataReader(graph=self.graph)
        opReader.FilePath.setValue(filepath)

        # The reader assumes xyzc order.
        # We have to transpose the data before we compare.
        opReorderAxes = OpReorderAxes(graph=self.graph)
        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"

        # Cleanup
        opReorderAxes.cleanUp()
        opReader.cleanUp()
    def test_Writer(self):
        opData = OpArrayCache( graph=self.graph )
        opData.blockShape.setValue( self.testData.shape )
        opData.Input.setValue( self.testData )
        
        opExport = OpExportMultipageTiffSequence(graph=self.graph)
        opExport.FilepathPattern.setValue( self._stack_filepattern )
        opExport.Input.connect( opData.Output )
        opExport.SliceIndexOffset.setValue(22)

        # Run the export
        opExport.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 produces txyzc 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"
        
        opReorderAxes.cleanUp()
        opReader.cleanUp()
    def test_basic(self):
        opData = OpArrayCache( graph=self.graph )
        opData.blockShape.setValue( self.testData.shape )
        opData.Input.setValue( self.testData )
        
        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 = OpInputDataReader( graph=self.graph )
        opReader.FilePath.setValue( filepath )

        # The reader assumes xyzc order.
        # We have to transpose the data before we compare.
        opReorderAxes = OpReorderAxes( graph=self.graph )
        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"
        
        # Cleanup
        opReorderAxes.cleanUp()
        opReader.cleanUp()
            def handleImportLabelsAction():
                # Find the directory of the most recently opened image file
                mostRecentImageFile = PreferencesManager().get(
                    'DataSelection', 'recent image')
                if mostRecentImageFile is not None:
                    defaultDirectory = os.path.split(mostRecentImageFile)[0]
                else:
                    defaultDirectory = os.path.expanduser('~')
                fileNames = DataSelectionGui.getImageFileNamesToOpen(
                    self, defaultDirectory)
                fileNames = map(str, fileNames)

                # For now, we require a single hdf5 file
                if len(fileNames) > 1:
                    QMessageBox.critical(
                        self, "Too many files",
                        "Labels must be contained in a single hdf5 volume.")
                    return
                if len(fileNames) == 0:
                    # user cancelled
                    return

                file_path = fileNames[0]
                internal_paths = DataSelectionGui.getPossibleInternalPaths(
                    file_path)
                if len(internal_paths) == 0:
                    QMessageBox.critical(
                        self, "No volumes in file",
                        "Couldn't find a suitable dataset in your hdf5 file.")
                    return
                if len(internal_paths) == 1:
                    internal_path = internal_paths[0]
                else:
                    dlg = H5VolumeSelectionDlg(internal_paths, self)
                    if dlg.exec_() == QDialog.Rejected:
                        return
                    selected_index = dlg.combo.currentIndex()
                    internal_path = str(internal_paths[selected_index])

                path_components = PathComponents(file_path)
                path_components.internalPath = str(internal_path)

                try:
                    top_op = self.topLevelOperatorView
                    opReader = OpInputDataReader(parent=top_op.parent)
                    opReader.FilePath.setValue(path_components.totalPath())

                    # Reorder the axes
                    op5 = OpReorderAxes(parent=top_op.parent)
                    op5.AxisOrder.setValue(
                        top_op.LabelInputs.meta.getAxisKeys())
                    op5.Input.connect(opReader.Output)

                    # Finally, import the labels
                    top_op.importLabels(top_op.current_view_index(),
                                        op5.Output)

                finally:
                    op5.cleanUp()
                    opReader.cleanUp()
    def testLotsOfOptions(self):
        #OLD_LAZYFLOW_STATUS_MONITOR_SECONDS = os.getenv("LAZYFLOW_STATUS_MONITOR_SECONDS", None)
        #os.environ["LAZYFLOW_STATUS_MONITOR_SECONDS"] = "1"
        
        # NOTE: In this test, cmd-line args to nosetests will also end up getting "parsed" by ilastik.
        #       That shouldn't be an issue, since the pixel classification workflow ignores unrecognized options.
        #       See if __name__ == __main__ section, below.
        args = []
        args.append( "--project=" + self.PROJECT_FILE )
        args.append( "--headless" )
        #args.append( "--sys_tmp_dir=/tmp" )
 
        # Batch export options
        args.append( '--export_source=Simple Segmentation' )
        args.append( '--output_format=png sequence' ) # If we were actually launching from the command line, 'png sequence' would be in quotes...
        args.append( "--output_filename_format={dataset_dir}/{nickname}_segmentation_z{slice_index}.png" )
        args.append( "--export_dtype=uint8" )
        args.append( "--output_axis_order=zxyc" )
         
        args.append( "--pipeline_result_drange=(0,2)" )
        args.append( "--export_drange=(0,255)" )
 
        args.append( "--cutout_subregion=[(0,50,50,0,0), (1, 150, 150, 50, 1)]" )
        args.append( self.SAMPLE_DATA )
 
        old_sys_argv = list(sys.argv)
        sys.argv = ['ilastik.py'] # Clear the existing commandline args so it looks like we're starting fresh.
        sys.argv += args
 
        # Start up the ilastik.py entry script as if we had launched it from the command line
        # This will execute the batch mode script
        try:
            self.ilastik_startup.main()
        finally:
            sys.argv = old_sys_argv
#             if OLD_LAZYFLOW_STATUS_MONITOR_SECONDS:
#                 os.environ["LAZYFLOW_STATUS_MONITOR_SECONDS"] = OLD_LAZYFLOW_STATUS_MONITOR_SECONDS
 
        output_path = self.SAMPLE_DATA[:-4] + "_segmentation_z{slice_index}.png"
        globstring = output_path.format( slice_index=999 )
        globstring = globstring.replace('999', '*')
 
        opReader = OpStackLoader( graph=Graph() )
        opReader.globstring.setValue( globstring )
 
        # (The OpStackLoader produces txyzc order.)
        opReorderAxes = OpReorderAxes( graph=Graph() )
        opReorderAxes.AxisOrder.setValue( 'tzyxc' )
        opReorderAxes.Input.connect( opReader.stack )
         
        try:
            readData = opReorderAxes.Output[:].wait()
     
            # Check basic attributes
            assert readData.shape[:-1] == self.data[0:1, 50:150, 50:150, 0:50, 0:1].shape[:-1] # Assume channel is last axis
            assert readData.shape[-1] == 1, "Wrong number of channels.  Expected 1, got {}".format( readData.shape[-1] )
        finally:
            # Clean-up.
            opReorderAxes.cleanUp()
            opReader.cleanUp()
Beispiel #6
0
    def test_Writer(self):
        opData = OpArrayCache(graph=self.graph)
        opData.blockShape.setValue(self.testData.shape)
        opData.Input.setValue(self.testData)

        opExport = OpExportMultipageTiffSequence(graph=self.graph)
        opExport.FilepathPattern.setValue(self._stack_filepattern)
        opExport.Input.connect(opData.Output)
        opExport.SliceIndexOffset.setValue(22)

        # Run the export
        opExport.run_export()

        globstring = self._stack_filepattern.format(slice_index=999)
        globstring = globstring.replace('999', '*')

        opReader = OpTiffSequenceReader(graph=self.graph)
        opReader.GlobString.setValue(globstring)

        # (The OpStackLoader produces txyzc order.)
        opReorderAxes = OpReorderAxes(graph=self.graph)
        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"

        opReorderAxes.cleanUp()
        opReader.cleanUp()
    def testLotsOfOptions(self):
        # NOTE: In this test, cmd-line args to nosetests will also end up getting "parsed" by ilastik.
        #       That shouldn't be an issue, since the pixel classification workflow ignores unrecognized options.
        #       See if __name__ == __main__ section, below.
        args = []
        args.append("--project=" + self.PROJECT_FILE)
        args.append("--headless")
        #args.append( "--sys_tmp_dir=/tmp" )

        # Batch export options
        args.append(
            '--output_format=png sequence'
        )  # If we were actually launching from the command line, 'png sequence' would be in quotes...
        args.append(
            "--output_filename_format={dataset_dir}/{nickname}_prediction_z{slice_index}.png"
        )
        args.append("--export_dtype=uint8")
        args.append("--output_axis_order=zxyc")

        args.append("--pipeline_result_drange=(0.0,1.0)")
        args.append("--export_drange=(0,255)")

        args.append("--cutout_subregion=[(0,50,50,0,0), (1, 150, 150, 50, 2)]")
        args.append(self.SAMPLE_DATA)

        sys.argv = [
            'ilastik.py'
        ]  # Clear the existing commandline args so it looks like we're starting fresh.
        sys.argv += args

        # Start up the ilastik.py entry script as if we had launched it from the command line
        # This will execute the batch mode script
        self.ilastik_startup.main()

        output_path = self.SAMPLE_DATA[:-4] + "_prediction_z{slice_index}.png"
        globstring = output_path.format(slice_index=999)
        globstring = globstring.replace('999', '*')

        opReader = OpStackLoader(graph=Graph())
        opReader.globstring.setValue(globstring)

        # (The OpStackLoader produces txyzc order.)
        opReorderAxes = OpReorderAxes(graph=Graph())
        opReorderAxes.AxisOrder.setValue('txyzc')
        opReorderAxes.Input.connect(opReader.stack)

        readData = opReorderAxes.Output[:].wait()

        # Check basic attributes
        assert readData.shape[:-1] == self.data[
            0:1, 50:150, 50:150, 0:50,
            0:2].shape[:-1]  # Assume channel is last axis
        assert readData.shape[
            -1] == 2, "Wrong number of channels.  Expected 2, got {}".format(
                readData.shape[-1])

        # Clean-up.
        opReorderAxes.cleanUp()
        opReader.cleanUp()
        def handleImportLabelsAction():
            # Find the directory of the most recently opened image file
            mostRecentImageFile = PreferencesManager().get( 'DataSelection', 'recent image' )
            if mostRecentImageFile is not None:
                defaultDirectory = os.path.split(mostRecentImageFile)[0]
            else:
                defaultDirectory = os.path.expanduser('~')
            fileNames = DataSelectionGui.getImageFileNamesToOpen(self, defaultDirectory)
            fileNames = list(map(str, fileNames))
            
            # For now, we require a single hdf5 file
            if len(fileNames) > 1:
                QMessageBox.critical(self, "Too many files", 
                                     "Labels must be contained in a single hdf5 volume.")
                return
            if len(fileNames) == 0:
                # user cancelled
                return
            
            file_path = fileNames[0]
            internal_paths = DataSelectionGui.getPossibleInternalPaths(file_path)
            if len(internal_paths) == 0:
                QMessageBox.critical(self, "No volumes in file", 
                                     "Couldn't find a suitable dataset in your hdf5 file.")
                return
            if len(internal_paths) == 1:
                internal_path = internal_paths[0]
            else:
                dlg = H5VolumeSelectionDlg(internal_paths, self)
                if dlg.exec_() == QDialog.Rejected:
                    return
                selected_index = dlg.combo.currentIndex()
                internal_path = str(internal_paths[selected_index])

            path_components = PathComponents(file_path)
            path_components.internalPath = str(internal_path)
            
            try:
                top_op = self.topLevelOperatorView
                opReader = OpInputDataReader(parent=top_op.parent)
                opReader.FilePath.setValue( path_components.totalPath() )
                
                # Reorder the axes
                op5 = OpReorderAxes(parent=top_op.parent)
                op5.AxisOrder.setValue( top_op.LabelInputs.meta.getAxisKeys() )
                op5.Input.connect( opReader.Output )
            
                # Finally, import the labels
                top_op.importLabels( top_op.current_view_index(), op5.Output )
                    
            finally:
                op5.cleanUp()
                opReader.cleanUp()
Beispiel #9
0
        def handleImportLabelsAction():
            fileNames = ImageFileDialog(
                self,
                preferences_group="DataSelection",
                preferences_setting="recent image").getSelectedPaths()
            fileNames = list(map(str, fileNames))

            # For now, we require a single hdf5 file
            if len(fileNames) > 1:
                QMessageBox.critical(
                    self, "Too many files",
                    "Labels must be contained in a single hdf5 volume.")
                return
            if len(fileNames) == 0:
                # user cancelled
                return

            file_path = fileNames[0]
            internal_paths = DatasetInfo.getPossibleInternalPathsFor(file_path)
            if len(internal_paths) == 0:
                QMessageBox.critical(
                    self, "No volumes in file",
                    "Couldn't find a suitable dataset in your hdf5 file.")
                return
            if len(internal_paths) == 1:
                internal_path = internal_paths[0]
            else:
                dlg = SubvolumeSelectionDlg(internal_paths, self)
                if dlg.exec_() == QDialog.Rejected:
                    return
                selected_index = dlg.combo.currentIndex()
                internal_path = str(internal_paths[selected_index])

            path_components = PathComponents(file_path)
            path_components.internalPath = str(internal_path)

            try:
                top_op = self.topLevelOperatorView
                opReader = OpInputDataReader(parent=top_op.parent)
                opReader.FilePath.setValue(path_components.totalPath())

                # Reorder the axes
                op5 = OpReorderAxes(parent=top_op.parent)
                op5.AxisOrder.setValue(top_op.LabelInputs.meta.getAxisKeys())
                op5.Input.connect(opReader.Output)

                # Finally, import the labels
                top_op.importLabels(top_op.current_view_index(), op5.Output)

            finally:
                op5.cleanUp()
                opReader.cleanUp()
Beispiel #10
0
    def getVoluminaShapeForSlot(self, slot):
        shape = None
        if slot.ready() and slot.meta.axistags is not None:
            # Use an OpReorderAxes adapter to transpose the shape for us.
            op5 = OpReorderAxes( parent=slot.getRealOperator().parent )
            op5.Input.connect( slot )
            shape = op5.Output.meta.shape

            # We just needed the operator to determine the transposed shape.
            # Disconnect it so it can be garbage collected.
            op5.Input.disconnect()
            op5.cleanUp()
        return shape
Beispiel #11
0
    def getVoluminaShapeForSlot(self, slot):
        shape = None
        if slot.ready() and slot.meta.axistags is not None:
            # Use an OpReorderAxes adapter to transpose the shape for us.
            op5 = OpReorderAxes(parent=slot.getRealOperator().parent)
            op5.Input.connect(slot)
            shape = op5.Output.meta.shape

            # We just needed the operator to determine the transposed shape.
            # Disconnect it so it can be garbage collected.
            op5.Input.disconnect()
            op5.cleanUp()
        return shape
    def testLotsOfOptions(self):
        # NOTE: In this test, cmd-line args to nosetests will also end up getting "parsed" by ilastik.
        #       That shouldn't be an issue, since the pixel classification workflow ignores unrecognized options.
        #       See if __name__ == __main__ section, below.
        args = []
        args.append( "--project=" + self.PROJECT_FILE )
        args.append( "--headless" )
        args.append( "--sys_tmp_dir=/tmp" )

        # Batch export options
        args.append( '--output_format=png sequence' ) # If we were actually launching from the command line, 'png sequence' would be in quotes...
        args.append( "--output_filename_format={dataset_dir}/{nickname}_prediction_z{slice_index}.png" )
        args.append( "--export_dtype=uint8" )
        args.append( "--output_axis_order=zxyc" )
        
        args.append( "--pipeline_result_drange=(0.0,1.0)" )
        args.append( "--export_drange=(0,255)" )

        args.append( "--cutout_subregion=[(0,50,50,0,0), (1, 150, 150, 50, 2)]" )
        args.append( self.SAMPLE_DATA )

        sys.argv = ['ilastik.py'] # Clear the existing commandline args so it looks like we're starting fresh.
        sys.argv += args

        # Start up the ilastik.py entry script as if we had launched it from the command line
        # This will execute the batch mode script
        ilastik_entry_file_path = os.path.join( os.path.split( ilastik.__file__ )[0], "../ilastik.py" )
        imp.load_source( 'main', ilastik_entry_file_path )

        output_path = self.SAMPLE_DATA[:-4] + "_prediction_z{slice_index}.png"
        globstring = output_path.format( slice_index=999 )
        globstring = globstring.replace('999', '*')

        opReader = OpStackLoader( graph=Graph() )
        opReader.globstring.setValue( globstring )

        # (The OpStackLoader produces txyzc order.)
        opReorderAxes = OpReorderAxes( graph=Graph() )
        opReorderAxes.AxisOrder.setValue( 'txyzc' )
        opReorderAxes.Input.connect( opReader.stack )
        
        readData = opReorderAxes.Output[:].wait()

        # Check basic attributes
        assert readData.shape[:-1] == self.data[0:1, 50:150, 50:150, 0:50, 0:2].shape[:-1] # Assume channel is last axis
        assert readData.shape[-1] == 2, "Wrong number of channels.  Expected 2, got {}".format( readData.shape[-1] )
        
        # Clean-up.
        opReorderAxes.cleanUp()
        opReader.cleanUp()
Beispiel #13
0
    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()
Beispiel #14
0
    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 test_basic(self):
        opSource = OpArrayPiper(graph=self.graph)
        opSource.Input.setValue(self.testData)

        opData = OpArrayCache(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 test_basic(self):
        opSource = OpArrayPiper(graph=self.graph)
        opSource.Input.setValue( self.testData )
        
        opData = OpArrayCache( 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 testLotsOfOptions(self):
        # OLD_LAZYFLOW_STATUS_MONITOR_SECONDS = os.getenv("LAZYFLOW_STATUS_MONITOR_SECONDS", None)
        # os.environ["LAZYFLOW_STATUS_MONITOR_SECONDS"] = "1"

        # NOTE: In this test, cmd-line args to tests will also end up getting "parsed" by ilastik.
        #       That shouldn't be an issue, since the pixel classification workflow ignores unrecognized options.
        #       See if __name__ == __main__ section, below.
        args = []
        args.append("--project=" + self.PROJECT_FILE)
        args.append("--headless")
        # args.append( "--sys_tmp_dir=/tmp" )

        # Batch export options
        args.append("--export_source=Simple Segmentation")
        args.append(
            "--output_format=png sequence"
        )  # If we were actually launching from the command line, 'png sequence' would be in quotes...
        args.append("--output_filename_format={dataset_dir}/{nickname}_segmentation_z{slice_index}.png")
        args.append("--export_dtype=uint8")
        args.append("--output_axis_order=zxyc")

        args.append("--pipeline_result_drange=(0,2)")
        args.append("--export_drange=(0,255)")

        args.append("--cutout_subregion=[(0,10,10,0,0), (1, 20, 20, 5, 1)]")
        args.append(self.SAMPLE_DATA)

        old_sys_argv = list(sys.argv)
        sys.argv = ["ilastik.py"]  # Clear the existing commandline args so it looks like we're starting fresh.
        sys.argv += args

        # Start up the ilastik.py entry script as if we had launched it from the command line
        # This will execute the batch mode script
        try:
            self.ilastik_startup.main()
        finally:
            sys.argv = old_sys_argv
        #             if OLD_LAZYFLOW_STATUS_MONITOR_SECONDS:
        #                 os.environ["LAZYFLOW_STATUS_MONITOR_SECONDS"] = OLD_LAZYFLOW_STATUS_MONITOR_SECONDS

        output_path = self.SAMPLE_DATA[:-4] + "_segmentation_z{slice_index}.png"
        globstring = output_path.format(slice_index=999)
        globstring = globstring.replace("999", "*")

        opReader = OpStackLoader(graph=Graph())
        opReader.globstring.setValue(globstring)

        # (The OpStackLoader produces txyzc order.)
        opReorderAxes = OpReorderAxes(graph=Graph())
        opReorderAxes.AxisOrder.setValue("tzyxc")
        opReorderAxes.Input.connect(opReader.stack)

        try:
            readData = opReorderAxes.Output[:].wait()

            # Check basic attributes
            assert readData.shape[:-1] == (1, 10, 10, 5), readData.shape[:-1]  # Assume channel is last axis
            assert readData.shape[-1] == 1, "Wrong number of channels.  Expected 1, got {}".format(readData.shape[-1])
        finally:
            # Clean-up.
            opReorderAxes.cleanUp()
            opReader.cleanUp()
Beispiel #18
0
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None):
    """
    Prompt the user for layer import settings, and perform the layer import.
    :param labelLayer: The top label layer source
    :param labelingSlots: An instance of LabelingGui.LabelingSlots
    :param parent_widget: The Qt GUI parent object
    """
    writeSeeds = labelingSlots.labelInput
    assert isinstance(
        writeSeeds,
        lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds))
    opLabels = writeSeeds.getRealOperator()
    assert isinstance(opLabels, lazyflow.graph.Operator
                      ), "slot's operator is of type %r" % (type(opLabels))

    recentlyImported = PreferencesManager().get('labeling',
                                                'recently imported')
    mostRecentProjectPath = PreferencesManager().get('shell',
                                                     'recently opened')
    mostRecentImageFile = PreferencesManager().get('DataSelection',
                                                   'recent image')
    if recentlyImported:
        defaultDirectory = os.path.split(recentlyImported)[0]
    elif mostRecentProjectPath:
        defaultDirectory = os.path.split(mostRecentProjectPath)[0]
    elif mostRecentImageFile:
        defaultDirectory = os.path.split(mostRecentImageFile)[0]
    else:
        defaultDirectory = os.path.expanduser('~')

    fileNames = DataSelectionGui.getImageFileNamesToOpen(
        parent_widget, defaultDirectory)
    fileNames = map(str, fileNames)

    if not fileNames:
        return

    PreferencesManager().set('labeling', 'recently imported', fileNames[0])

    try:
        # Initialize operators
        opImport = OpInputDataReader(parent=opLabels.parent)
        opCache = OpArrayCache(parent=opLabels.parent)
        opMetadataInjector = OpMetadataInjector(parent=opLabels.parent)
        opReorderAxes = OpReorderAxes(parent=opLabels.parent)

        # Set up the pipeline as follows:
        #
        #   opImport --> opCache --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput
        #                           /                            /
        #   User-specified axisorder    labelInput.meta.axistags

        opImport.WorkingDirectory.setValue(defaultDirectory)
        opImport.FilePath.setValue(fileNames[0] if len(fileNames) ==
                                   1 else os.path.pathsep.join(fileNames))
        assert opImport.Output.ready()

        opCache.blockShape.setValue(opImport.Output.meta.shape)
        opCache.Input.connect(opImport.Output)
        assert opCache.Output.ready()

        opMetadataInjector.Input.connect(opCache.Output)
        metadata = opCache.Output.meta.copy()
        opMetadataInjector.Metadata.setValue(metadata)
        opReorderAxes.Input.connect(opMetadataInjector.Output)

        # Transpose the axes for assignment to the labeling operator.
        opReorderAxes.AxisOrder.setValue(writeSeeds.meta.getAxisKeys())

        # We'll show a little window with a busy indicator while the data is loading
        busy_dlg = QProgressDialog(parent=parent_widget)
        busy_dlg.setLabelText("Importing Label Data...")
        busy_dlg.setCancelButton(None)
        busy_dlg.setMinimum(100)
        busy_dlg.setMaximum(100)

        def close_busy_dlg(*args):
            QApplication.postEvent(busy_dlg, QCloseEvent())

        # Load the data from file into our cache
        # When it's done loading, close the progress dialog.
        req = opCache.Output[:]
        req.notify_finished(close_busy_dlg)
        req.notify_failed(close_busy_dlg)
        req.submit()
        busy_dlg.exec_()

        readData = req.result

        maxLabels = len(labelingSlots.labelNames.value)

        # Can't use return_counts feature because that requires numpy >= 1.9
        #unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True)

        # This does the same as the above, albeit slower, and probably with more ram.
        unique_read_labels = numpy.unique(readData)
        readLabelCounts = numpy.bincount(readData.flat)[unique_read_labels]

        labelInfo = (maxLabels, (unique_read_labels, readLabelCounts))
        del readData

        # Ask the user how to interpret the data.
        settingsDlg = LabelImportOptionsDlg(parent_widget, fileNames,
                                            opMetadataInjector.Output,
                                            labelingSlots.labelInput,
                                            labelInfo)

        def handle_updated_axes():
            # The user is specifying a new interpretation of the file's axes
            updated_axisorder = str(settingsDlg.axesEdit.text())
            metadata = opMetadataInjector.Metadata.value.copy()
            metadata.axistags = vigra.defaultAxistags(updated_axisorder)
            opMetadataInjector.Metadata.setValue(metadata)

        settingsDlg.axesEdit.editingFinished.connect(handle_updated_axes)

        dlg_result = settingsDlg.exec_()
        if dlg_result != LabelImportOptionsDlg.Accepted:
            return

        # Get user's chosen label mapping from dlg
        labelMapping = settingsDlg.labelMapping

        # Get user's chosen offsets.
        # Offsets in dlg only include the file axes, not the 5D axes expected by the label input,
        # so expand them to full 5D
        axes_5d = opReorderAxes.Output.meta.getAxisKeys()
        tagged_offsets = collections.OrderedDict(
            zip(axes_5d, [0] * len(axes_5d)))
        tagged_offsets.update(
            dict(
                zip(opMetadataInjector.Output.meta.getAxisKeys(),
                    settingsDlg.imageOffsets)))
        imageOffsets = tagged_offsets.values()

        # Optimization if mapping is identity
        if labelMapping.keys() == labelMapping.values():
            labelMapping = None

        # This will be fast (it's already cached)
        label_data = opReorderAxes.Output[:].wait()

        # Map input labels to output labels
        if labelMapping:
            # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential)
            # But this supports potentially huge values of unique_read_labels (in the billions),
            # without needing GB of RAM.
            mapping_indexes = numpy.searchsorted(unique_read_labels,
                                                 label_data)
            new_labels = numpy.array(
                [labelMapping[x] for x in unique_read_labels])
            label_data[:] = new_labels[mapping_indexes]

        label_roi = numpy.array(roiFromShape(opReorderAxes.Output.meta.shape))
        label_roi += imageOffsets
        label_slice = roiToSlice(*label_roi)
        writeSeeds[label_slice] = label_data

    finally:
        opReorderAxes.cleanUp()
        opMetadataInjector.cleanUp()
        opCache.cleanUp()
        opImport.cleanUp()
Beispiel #19
0
        def impl():
            shell = self.shell
            workflow = shell.projectManager.workflow
            carvingApplet = workflow.carvingApplet
            gui = carvingApplet.getMultiLaneGui()
            op_carving = carvingApplet.topLevelOperator.getLane(0)

            # activate the carving applet
            shell.setSelectedAppletDrawer(2)
            # let the gui catch up
            QApplication.processEvents()
            self.waitForViews(gui.currentGui().editor.imageViews)
            # inject the labels
            op5 = OpReorderAxes(parent=op_carving.parent)
            opReader = OpInputDataReader(parent=op_carving.parent)
            try:
                opReader.FilePath.setValue(f"{self.reference_files['carving_label_file']}/exported_data")
                op5.AxisOrder.setValue(op_carving.WriteSeeds.meta.getAxisKeys())
                op5.Input.connect(opReader.Output)
                label_data = op5.Output[:].wait()
            finally:
                op5.cleanUp()
                opReader.cleanUp()
            slicing = roi.fullSlicing(label_data.shape)
            op_carving.WriteSeeds[slicing] = label_data

            gui.currentGui().labelingDrawerUi.segment.click()
            QApplication.processEvents()

            op_carving.saveObjectAs("Object 1")
            op_carving.deleteObject("<not saved yet>")

            # export the mesh:
            req = gui.currentGui()._exportMeshes(["Object 1"], [self.output_obj_file])
            req.wait()

            # compare meshes
            with open(self.output_obj_file, "r") as f:
                left = f.read()

            with open(self.reference_files["output_obj_file"], "r") as f:
                right = f.read()

            # TODO: might result in errors due to rounding on different systems
            assert left == right

            # export the completed segments layer
            layermatch = [
                x.name.startswith("Completed segments (unicolor)") for x in gui.currentGui().editor.layerStack
            ]
            assert sum(layermatch) == 1, "Completed segments (unicolor) Layer expected."
            completed_segments_layer = gui.currentGui().editor.layerStack[layermatch.index(True)]
            opExport = get_export_operator(completed_segments_layer)
            try:
                opExport.OutputFilenameFormat.setValue(self.output_file)
                opExport.run_export()
            finally:
                opExport.cleanUp()

            assert os.path.exists(self.output_file)

            # compare completed segments
            with h5py.File(self.reference_files["output_file"], "r") as f_left:
                data_left = f_left["exported_data"][:]

            with h5py.File(self.output_file, "r") as f_right:
                data_right = f_right["exported_data"][:]

            numpy.testing.assert_array_almost_equal(data_left, data_right)

            # Save the project
            saveThread = self.shell.onSaveProjectActionTriggered()
            saveThread.join()
Beispiel #20
0
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None):
    """
    Prompt the user for layer import settings, and perform the layer import.
    :param labelLayer: The top label layer source
    :param labelingSlots: An instance of LabelingGui.LabelingSlots
    :param parent_widget: The Qt GUI parent object
    """
    writeSeeds = labelingSlots.labelInput
    assert isinstance(
        writeSeeds,
        lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds))
    opLabels = writeSeeds.getRealOperator()
    assert isinstance(opLabels, lazyflow.graph.Operator
                      ), "slot's operator is of type %r" % (type(opLabels))

    recentlyImported = PreferencesManager().get('labeling',
                                                'recently imported')
    mostRecentProjectPath = PreferencesManager().get('shell',
                                                     'recently opened')
    mostRecentImageFile = PreferencesManager().get('DataSelection',
                                                   'recent image')
    if recentlyImported:
        defaultDirectory = os.path.split(recentlyImported)[0]
    elif mostRecentProjectPath:
        defaultDirectory = os.path.split(mostRecentProjectPath)[0]
    elif mostRecentImageFile:
        defaultDirectory = os.path.split(mostRecentImageFile)[0]
    else:
        defaultDirectory = os.path.expanduser('~')

    fileNames = DataSelectionGui.getImageFileNamesToOpen(
        parent_widget, defaultDirectory)
    fileNames = map(str, fileNames)

    if not fileNames:
        return

    PreferencesManager().set('labeling', 'recently imported', fileNames[0])

    try:
        # Initialize operators
        opImport = OpInputDataReader(parent=opLabels.parent)
        opCache = OpBlockedArrayCache(parent=opLabels.parent)
        opMetadataInjector = OpMetadataInjector(parent=opLabels.parent)
        opReorderAxes = OpReorderAxes(parent=opLabels.parent)

        # Set up the pipeline as follows:
        #
        #   opImport --> (opCache) --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput
        #                             /                            /
        #     User-specified axisorder    labelInput.meta.axistags

        opImport.WorkingDirectory.setValue(defaultDirectory)
        opImport.FilePath.setValue(fileNames[0] if len(fileNames) ==
                                   1 else os.path.pathsep.join(fileNames))
        assert opImport.Output.ready()

        maxLabels = len(labelingSlots.labelNames.value)

        # We don't bother with counting the label pixels
        # (and caching the data) if it's big (1 GB)
        if numpy.prod(opImport.Output.meta.shape) > 1e9:
            reading_slot = opImport.Output

            # For huge data, we don't go through and search for the pixel values,
            # because that takes an annoyingly long amount of time.
            # Instead, we make the reasonable assumption that the input labels are already 1,2,3..N
            # and we don't tell the user what the label pixel counts are.
            unique_read_labels = numpy.array(range(maxLabels + 1))
            readLabelCounts = numpy.array([-1] * (maxLabels + 1))
            labelInfo = (maxLabels, (unique_read_labels, readLabelCounts))
        else:
            opCache.Input.connect(opImport.Output)
            opCache.CompressionEnabled.setValue(True)
            assert opCache.Output.ready()
            reading_slot = opCache.Output

            # We'll show a little window with a busy indicator while the data is loading
            busy_dlg = QProgressDialog(parent=parent_widget)
            busy_dlg.setLabelText("Scanning Label Data...")
            busy_dlg.setCancelButton(None)
            busy_dlg.setMinimum(100)
            busy_dlg.setMaximum(100)

            def close_busy_dlg(*args):
                QApplication.postEvent(busy_dlg, QCloseEvent())

            # Load the data from file into our cache
            # When it's done loading, close the progress dialog.
            req = reading_slot[:]
            req.notify_finished(close_busy_dlg)
            req.notify_failed(close_busy_dlg)
            req.submit()
            busy_dlg.exec_()

            readData = req.result

            # Can't use return_counts feature because that requires numpy >= 1.9
            #unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True)

            # This does the same as the above, albeit slower, and probably with more ram.
            bincounts = chunked_bincount(readData)
            unique_read_labels = bincounts.nonzero()[0].astype(readData.dtype,
                                                               copy=False)
            readLabelCounts = bincounts[unique_read_labels]

            labelInfo = (maxLabels, (unique_read_labels, readLabelCounts))
            del readData

        opMetadataInjector.Input.connect(reading_slot)
        metadata = reading_slot.meta.copy()
        opMetadataInjector.Metadata.setValue(metadata)
        opReorderAxes.Input.connect(opMetadataInjector.Output)

        # Transpose the axes for assignment to the labeling operator.
        opReorderAxes.AxisOrder.setValue(writeSeeds.meta.getAxisKeys())

        # Ask the user how to interpret the data.
        settingsDlg = LabelImportOptionsDlg(parent_widget, fileNames,
                                            opMetadataInjector.Output,
                                            labelingSlots.labelInput,
                                            labelInfo)

        def handle_updated_axes():
            # The user is specifying a new interpretation of the file's axes
            updated_axisorder = str(settingsDlg.axesEdit.text())
            metadata = opMetadataInjector.Metadata.value.copy()
            metadata.axistags = vigra.defaultAxistags(updated_axisorder)
            opMetadataInjector.Metadata.setValue(metadata)

            if opReorderAxes._invalid_axes:
                settingsDlg.buttonBox.button(
                    QDialogButtonBox.Ok).setEnabled(False)
                # Red background
                settingsDlg.axesEdit.setStyleSheet(
                    "QLineEdit { background: rgb(255, 128, 128);"
                    "selection-background-color: rgb(128, 128, 255); }")

        settingsDlg.axesEdit.editingFinished.connect(handle_updated_axes)

        # Initialize
        handle_updated_axes()

        dlg_result = settingsDlg.exec_()
        if dlg_result != LabelImportOptionsDlg.Accepted:
            return

        # Get user's chosen label mapping from dlg
        labelMapping = settingsDlg.labelMapping

        # Get user's chosen offsets, ordered by the 'write seeds' slot
        axes_5d = opReorderAxes.Output.meta.getAxisKeys()
        tagged_offsets = collections.OrderedDict(
            zip(axes_5d, [0] * len(axes_5d)))
        tagged_offsets.update(
            dict(
                zip(opReorderAxes.Output.meta.getAxisKeys(),
                    settingsDlg.imageOffsets)))
        imageOffsets = tagged_offsets.values()

        # Optimization if mapping is identity
        if labelMapping.keys() == labelMapping.values():
            labelMapping = None

        # If the data was already cached, this will be fast.
        label_data = opReorderAxes.Output[:].wait()

        # Map input labels to output labels
        if labelMapping:
            # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential)
            # But this supports potentially huge values of unique_read_labels (in the billions),
            # without needing GB of RAM.
            mapping_indexes = numpy.searchsorted(unique_read_labels,
                                                 label_data)
            new_labels = numpy.array(
                [labelMapping[x] for x in unique_read_labels])
            label_data[:] = new_labels[mapping_indexes]

        label_roi = numpy.array(roiFromShape(opReorderAxes.Output.meta.shape))
        label_roi += imageOffsets
        label_slice = roiToSlice(*label_roi)
        writeSeeds[label_slice] = label_data

    finally:
        opReorderAxes.cleanUp()
        opMetadataInjector.cleanUp()
        opCache.cleanUp()
        opImport.cleanUp()
Beispiel #21
0
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None):
    """
    Prompt the user for layer import settings, and perform the layer import.
    :param labelLayer: The top label layer source
    :param labelingSlots: An instance of LabelingGui.LabelingSlots
    :param parent_widget: The Qt GUI parent object
    """
    writeSeeds = labelingSlots.labelInput
    assert isinstance(writeSeeds, lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds))
    opLabels = writeSeeds.getRealOperator()
    assert isinstance(opLabels, lazyflow.graph.Operator), "slot's operator is of type %r" % (type(opLabels))


    recentlyImported = PreferencesManager().get('labeling', 'recently imported')
    mostRecentProjectPath = PreferencesManager().get('shell', 'recently opened')
    mostRecentImageFile = PreferencesManager().get( 'DataSelection', 'recent image' )
    if recentlyImported:
        defaultDirectory = os.path.split(recentlyImported)[0]
    elif mostRecentProjectPath:
        defaultDirectory = os.path.split(mostRecentProjectPath)[0]
    elif mostRecentImageFile:
        defaultDirectory = os.path.split(mostRecentImageFile)[0]
    else:
        defaultDirectory = os.path.expanduser('~')

    fileNames = DataSelectionGui.getImageFileNamesToOpen(parent_widget, defaultDirectory)
    fileNames = map(str, fileNames)

    if not fileNames:
        return

    PreferencesManager().set('labeling', 'recently imported', fileNames[0])

    try:
        # Initialize operators
        opImport = OpInputDataReader( parent=opLabels.parent )
        opCache = OpArrayCache( parent=opLabels.parent )
        opMetadataInjector = OpMetadataInjector( parent=opLabels.parent )
        opReorderAxes = OpReorderAxes( parent=opLabels.parent )
    
        # Set up the pipeline as follows:
        #
        #   opImport --> opCache --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput
        #                           /                            /
        #   User-specified axisorder    labelInput.meta.axistags
    
        opImport.WorkingDirectory.setValue(defaultDirectory)
        opImport.FilePath.setValue(fileNames[0] if len(fileNames) == 1 else
                                   os.path.pathsep.join(fileNames))
        assert opImport.Output.ready()
    
        opCache.blockShape.setValue( opImport.Output.meta.shape )
        opCache.Input.connect( opImport.Output )
        assert opCache.Output.ready()

        opMetadataInjector.Input.connect( opCache.Output )
        metadata = opCache.Output.meta.copy()
        opMetadataInjector.Metadata.setValue( metadata )
        opReorderAxes.Input.connect( opMetadataInjector.Output )

        # Transpose the axes for assignment to the labeling operator.
        opReorderAxes.AxisOrder.setValue( writeSeeds.meta.getAxisKeys() )
    
        # We'll show a little window with a busy indicator while the data is loading
        busy_dlg = QProgressDialog(parent=parent_widget)
        busy_dlg.setLabelText("Importing Label Data...")
        busy_dlg.setCancelButton(None)
        busy_dlg.setMinimum(100)
        busy_dlg.setMaximum(100)
        def close_busy_dlg(*args):
            QApplication.postEvent(busy_dlg, QCloseEvent())
    
        # Load the data from file into our cache
        # When it's done loading, close the progress dialog.
        req = opCache.Output[:]
        req.notify_finished( close_busy_dlg )
        req.notify_failed( close_busy_dlg )
        req.submit()
        busy_dlg.exec_()

        readData = req.result
        
        maxLabels = len(labelingSlots.labelNames.value)

        # Can't use return_counts feature because that requires numpy >= 1.9
        #unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True)

        # This does the same as the above, albeit slower, and probably with more ram.
        unique_read_labels = numpy.unique(readData)
        readLabelCounts = vigra_bincount(readData)[unique_read_labels]

        labelInfo = (maxLabels, (unique_read_labels, readLabelCounts))
        del readData
    
        # Ask the user how to interpret the data.
        settingsDlg = LabelImportOptionsDlg( parent_widget,
                                             fileNames, opMetadataInjector.Output,
                                             labelingSlots.labelInput, labelInfo )

        def handle_updated_axes():
            # The user is specifying a new interpretation of the file's axes
            updated_axisorder = str(settingsDlg.axesEdit.text())
            metadata = opMetadataInjector.Metadata.value.copy()
            metadata.axistags = vigra.defaultAxistags(updated_axisorder)
            opMetadataInjector.Metadata.setValue( metadata )
            
            if opReorderAxes._invalid_axes:
                settingsDlg.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
                # Red background
                settingsDlg.axesEdit.setStyleSheet("QLineEdit { background: rgb(255, 128, 128);"
                                                   "selection-background-color: rgb(128, 128, 255); }")
        settingsDlg.axesEdit.editingFinished.connect( handle_updated_axes )
        
        # Initialize
        handle_updated_axes()

        dlg_result = settingsDlg.exec_()
        if dlg_result != LabelImportOptionsDlg.Accepted:
            return

        # Get user's chosen label mapping from dlg
        labelMapping = settingsDlg.labelMapping    

        # Get user's chosen offsets.
        # Offsets in dlg only include the file axes, not the 5D axes expected by the label input,
        # so expand them to full 5D 
        axes_5d = opReorderAxes.Output.meta.getAxisKeys()
        tagged_offsets = collections.OrderedDict( zip( axes_5d, [0]*len(axes_5d) ) )
        tagged_offsets.update( dict( zip( opMetadataInjector.Output.meta.getAxisKeys(), settingsDlg.imageOffsets ) ) )
        imageOffsets = tagged_offsets.values()

        # Optimization if mapping is identity
        if labelMapping.keys() == labelMapping.values():
            labelMapping = None

        # This will be fast (it's already cached)
        label_data = opReorderAxes.Output[:].wait()
        
        # Map input labels to output labels
        if labelMapping:
            # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential)
            # But this supports potentially huge values of unique_read_labels (in the billions),
            # without needing GB of RAM.
            mapping_indexes = numpy.searchsorted(unique_read_labels, label_data)
            new_labels = numpy.array([labelMapping[x] for x in unique_read_labels])
            label_data[:] = new_labels[mapping_indexes]

        label_roi = numpy.array( roiFromShape(opReorderAxes.Output.meta.shape) )
        label_roi += imageOffsets
        label_slice = roiToSlice(*label_roi)
        writeSeeds[label_slice] = label_data

    finally:
        opReorderAxes.cleanUp()
        opMetadataInjector.cleanUp()
        opCache.cleanUp()
        opImport.cleanUp()
Beispiel #22
0
        def impl():
            shell = self.shell
            workflow = shell.projectManager.workflow
            carvingApplet = workflow.carvingApplet
            gui = carvingApplet.getMultiLaneGui()
            op_carving = carvingApplet.topLevelOperator.getLane(0)

            # activate the carving applet
            shell.setSelectedAppletDrawer(2)
            # let the gui catch up
            QApplication.processEvents()
            self.waitForViews(gui.currentGui().editor.imageViews)
            # inject the labels
            op5 = OpReorderAxes(parent=op_carving.parent)
            opReader = OpInputDataReader(parent=op_carving.parent)
            try:
                opReader.FilePath.setValue(f"{self.reference_files['carving_label_file']}/exported_data")
                op5.AxisOrder.setValue(op_carving.WriteSeeds.meta.getAxisKeys())
                op5.Input.connect(opReader.Output)
                label_data = op5.Output[:].wait()
            finally:
                op5.cleanUp()
                opReader.cleanUp()
            slicing = roi.fullSlicing(label_data.shape)
            op_carving.WriteSeeds[slicing] = label_data

            gui.currentGui().labelingDrawerUi.segment.click()
            QApplication.processEvents()

            op_carving.saveObjectAs("Object 1")
            op_carving.deleteObject("<not saved yet>")

            # export the mesh:
            req = gui.currentGui()._exportMeshes(["Object 1"], [self.output_obj_file])
            req.wait()

            # compare meshes
            with open(self.output_obj_file, "r") as f:
                left = f.read()

            with open(self.reference_files["output_obj_file"], "r") as f:
                right = f.read()

            # TODO: might result in errors due to rounding on different systems
            assert left == right

            # export the completed segments layer
            layermatch = [
                x.name.startswith("Completed segments (unicolor)") for x in gui.currentGui().editor.layerStack
            ]
            assert sum(layermatch) == 1, "Completed segments (unicolor) Layer expected."
            completed_segments_layer = gui.currentGui().editor.layerStack[layermatch.index(True)]
            opExport = get_export_operator(completed_segments_layer)
            try:
                opExport.OutputFilenameFormat.setValue(self.output_file)
                opExport.run_export()
            finally:
                opExport.cleanUp()

            assert os.path.exists(self.output_file)

            # compare completed segments
            with h5py.File(self.reference_files["output_file"], "r") as f_left:
                data_left = f_left["exported_data"][:]

            with h5py.File(self.output_file, "r") as f_right:
                data_right = f_right["exported_data"][:]

            numpy.testing.assert_array_almost_equal(data_left, data_right)

            # Save the project
            saveThread = self.shell.onSaveProjectActionTriggered()
            saveThread.join()