Ilastik: running batch export from python, with python data structures

I’ve had a script floating round for a while for doing this, but the python API seems to change every release.

I have a pre-trained 2-stage autocontext ILP which I want to open in python, and then hand it a numpy array and get a numpy array back (i.e. not having to read from a file and then write back to a file). It would also be fine to request a region of the project’s raw data stack, instead of handing it an array.

A very cut-down version of my script looks like this (it’s basically just the example at https://github.com/ilastik/ilastik/blob/0b94ea8104e38bda5eb17b1b23df9ed54f689a8f/examples/example_python_client.py ):

from collections import OrderedDict
import ilastik_main
import numpy as np
import vigra
from ilastik.applets.dataSelection import DatasetInfo

# open the project
args = ilastik_main.parse_args([])
args.headless = True
args.readonly = True
args.project = "path/to/my/project.ilp"

shell = ilastik_main.main(args)

# get the top-level operator for the 2nd stage of the autocontext
pixel_classifier = shell.workflow.pcApplets[-1].topLevelOperator

input_data = vigra.taggedView(np.random.randint(0, 255, (100, 100, 1), dtype=np.uint8), "yxc")  # or whatever

role_data_dict = OrderedDict([
    ("Raw Data", [ DatasetInfo(preloaded_array=input_data1)])
])

predictions = shell.workflow.batchProcessingApplet.run_export(role_data_dict, export_to_array=True)

The output I get is

WARNING dataset.py(313): H5pyDeprecationWarning: dataset.value has been deprecated. Use dataset[()] instead.
WARNING stype.py(187): UserWarning: ArrayLike.isCompatible: FIXME here
WARNING opSimpleBlockedArrayCache.py(43): FutureWarning: Conversion of the second argument of issubdtype from `dtype` to `np.generic` is deprecated. In future, it will be treated as `np.object_ == np.dtype(dtype).type`.
WARNING opSlicedBlockedArrayCache.py(141): FutureWarning: Conversion of the second argument of issubdtype from `dtype` to `np.generic` is deprecated. In future, it will be treated as `np.object_ == np.dtype(dtype).type`.
WARNING opFormattedDataExport.py(149): UserWarning: The ROI you are attempting to export exceeds the extents of your dataset.  Clipping to dataset bounds.
Traceback (most recent call last):
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 131, in run_export
    export_to_array=export_to_array)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 239, in _run_export_with_empty_batch_lane
    opDataSelectionBatchLaneView.DatasetGroup[role_index].setValue(info)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 124, in call_in_setup_context
    return func(self, *args, **kwargs)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1267, in setValue
    self._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1470, in _changed
    c._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1470, in _changed
    c._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1476, in _changed
    self._configureOperator(self)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1490, in _configureOperator
    self.operator._setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operator.py", line 469, in _setupOutputs
    self.setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/applets/dataExport/opDataExport.py", line 210, in setupOutputs
    self._opFormattedExport.Input.connect( self.Inputs[selection_index] )
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 124, in call_in_setup_context
    return func(self, *args, **kwargs)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 592, in connect
    self._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1476, in _changed
    self._configureOperator(self)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1490, in _configureOperator
    self.operator._setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operator.py", line 469, in _setupOutputs
    self.setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operators/ioOperators/opFormattedDataExport.py", line 231, in setupOutputs
    known_keys = {"roi": list(self._opSubRegion.Roi.value)}
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1145, in value
    temp = self[:].wait()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1068, in __getitem__
    raise Slot.SlotNotReadyError(slotInfoMsg)
lazyflow.slot.Slot.SlotNotReadyError: Can't get data from slot <class 'lazyflow.operators.generic.OpSubRegion'>.Roi yet. It isn't ready.First upstream problem slot is: OpSubRegion/OpSubRegion.Roi : 	{_ready : False, shape : None, has_mask : None, _dirty : False}
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/barnesc/.pyenv/versions/ilastik2019/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3325, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-0df88d0ccda3>", line 1, in <module>
    runfile('/home/barnesc/work/code/ilastik-tst/example_python_client.py', wdir='/home/barnesc/work/code/ilastik-tst')
  File "/home/barnesc/.local/share/JetBrains/Toolbox/apps/PyCharm-P/ch-0/191.7479.30/helpers/pydev/_pydev_bundle/pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "/home/barnesc/.local/share/JetBrains/Toolbox/apps/PyCharm-P/ch-0/191.7479.30/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/home/barnesc/work/code/ilastik-tst/example_python_client.py", line 77, in <module>
    predictions = shell.workflow.batchProcessingApplet.run_export(role_data_dict, export_to_array=True)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 141, in run_export
    batch_lane_index, batch_lane_index)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/applets/dataSelection/opDataSelection.py", line 646, in removeLane
    super(OpMultiLaneDataSelectionGroup, self).removeLane(laneIndex, finalLength)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/utility/opMultiLaneWrapper.py", line 43, in removeLane
    self._removeInnerOperator(laneIndex, numLanes-1)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operatorWrapper.py", line 285, in _removeInnerOperator
    oslot.removeSlot(index, length)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 124, in call_in_setup_context
    return func(self, *args, **kwargs)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 818, in removeSlot
    slot.disconnect()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 124, in call_in_setup_context
    return func(self, *args, **kwargs)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 674, in disconnect
    slot.disconnect()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 124, in call_in_setup_context
    return func(self, *args, **kwargs)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 699, in disconnect
    self._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1470, in _changed
    c._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1470, in _changed
    c._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1476, in _changed
    self._configureOperator(self)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1490, in _configureOperator
    self.operator._setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operator.py", line 469, in _setupOutputs
    self.setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/ilastik/ilastik/applets/dataExport/opDataExport.py", line 250, in setupOutputs
    self._opFormattedExport.TransactionSlot.connect( self.TransactionSlot )
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 124, in call_in_setup_context
    return func(self, *args, **kwargs)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 592, in connect
    self._changed()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1476, in _changed
    self._configureOperator(self)
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1490, in _configureOperator
    self.operator._setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operator.py", line 469, in _setupOutputs
    self.setupOutputs()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/operators/ioOperators/opFormattedDataExport.py", line 231, in setupOutputs
    known_keys = {"roi": list(self._opSubRegion.Roi.value)}
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1145, in value
    temp = self[:].wait()
  File "/home/barnesc/.pyenv/versions/ilastik2019/ilastik-meta/lazyflow/lazyflow/slot.py", line 1068, in __getitem__
    raise Slot.SlotNotReadyError(slotInfoMsg)
lazyflow.slot.Slot.SlotNotReadyError: Can't get data from slot <class 'lazyflow.operators.generic.OpSubRegion'>.Roi yet. It isn't ready.First upstream problem slot is: OpSubRegion/OpSubRegion.Roi : 	{_ready : False, shape : None, has_mask : None, _dirty : False}

I don’t know if there’s any documentation of the python API; the pages on github.io are pretty old. Not really sure where to begin.

Hi @clbarnes,

thanks for providing the example, that made it very easy to try on my own. When I run this code (with the one typo corrected input_data1 -> input_data) it simply works with the current master.

My guess is that maybe something is off with your project file? Have you tried opening it in the ilastik GUI, does that work?

On a side note: There will be a lot happening on the API side of things in the coming months. We’ll try to make it way easier calling ilastik from Python.

Sorry about that typo! My project file works fine in the GUI. What’s the correct way to install the current master into an existing conda environment? I’m not too familiar with conda deployment so the various recipes, feedstocks, and meta repositories are going over my head!

My next step is going to be trying the headless mode from the command line; not sure if that would be diagnostically valuable.

Great to hear the API will be evolving! Ilastik is such a powerful tool and great point of access for image analysis; having the flexibility of more easily using it as a backend for a python workflow would be amazing as it’s something I’ve struggled with.

Turns out I also cannot run ilastik from headless mode:

LAZYFLOW_THREADS=25 LAZYFLOW_TOTAL_RAM_MB=100000 $PYENV_VIRTUAL_ENV/run_ilastik.sh \
--readonly \
--headless \
--project full-vol-autocontext_n5.ilp \
--export_source "Probabilities Stage 2" \
--output_format "compressed n5" \
--logfile "log.txt" \
--output_filename_format "output.n5" \
excised.n5
INFO 2019-07-09 13:48:33,777 filterOperators 31461 140311977506560 Using fast filters.
WARNING 2019-07-09 13:48:33,784 warnings 31461 140311977506560 __init__.py(20): UserWarning: init: Could not import tiktorch classifier
INFO 2019-07-09 13:48:33,918 ilastik_main 31461 140311977506560 Starting ilastik from "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019".
INFO 2019-07-09 13:48:34,034 ilastik_main 31461 140311977506560 Resetting lazyflow thread pool with 25 threads.
INFO 2019-07-09 13:48:34,043 ilastik_main 31461 140311977506560 Configuring lazyflow RAM limit to 97.7GiB
INFO 2019-07-09 13:48:34,043 memory 31461 140311977506560 Available memory set to 97.7GiB
WARNING 2019-07-09 13:48:36,531 opConservationTracking 31461 140311977506560 Could not find any ILP solver
WARNING 2019-07-09 13:48:36,540 opStructuredTracking 31461 140311977506560 Could not find any ILP solver
WARNING 2019-07-09 13:48:36,541 structuredTrackingWorkflow 31461 140311977506560 Could not find any learning solver. Tracking will use flow-based solver (DPCT). Learning for tracking will be disabled!
INFO 2019-07-09 13:48:36,727 projectManager 31461 140311977506560 Opening Project: full-vol-autocontext_n5.ilp
WARNING 2019-07-09 13:48:36,729 warnings 31461 140311977506560 dataset.py(313): H5pyDeprecationWarning: dataset.value has been deprecated. Use dataset[()] instead.
WARNING 2019-07-09 13:48:36,761 warnings 31461 140311977506560 stype.py(187): UserWarning: ArrayLike.isCompatible: FIXME here
INFO 2019-07-09 13:48:36,977 acceleratesupport 31461 140311977506560 OpenGL_accelerate module loaded
INFO 2019-07-09 13:48:36,984 arraydatatype 31461 140311977506560 Using accelerated ArrayDatatype
WARNING 2019-07-09 13:48:37,644 warnings 31461 140311977506560 opSimpleBlockedArrayCache.py(43): FutureWarning: Conversion of the second argument of issubdtype from `dtype` to `np.generic` is deprecated. In future, it will be treated as `np.object_ == np.dtype(dtype).type`.
WARNING 2019-07-09 13:48:37,656 warnings 31461 140311977506560 opSlicedBlockedArrayCache.py(141): FutureWarning: Conversion of the second argument of issubdtype from `dtype` to `np.generic` is deprecated. In future, it will be treated as `np.object_ == np.dtype(dtype).type`.
INFO 2019-07-09 13:48:48,078 filterOperators 31681 140600484841216 Using fast filters.
WARNING 2019-07-09 13:48:48,083 warnings 31681 140600484841216 __init__.py(20): UserWarning: init: Could not import tiktorch classifier
INFO 2019-07-09 13:48:48,204 ilastik_main 31681 140600484841216 Starting ilastik from "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019".
INFO 2019-07-09 13:48:48,204 ilastik_main 31681 140600484841216 Resetting lazyflow thread pool with 25 threads.
INFO 2019-07-09 13:48:48,212 ilastik_main 31681 140600484841216 Configuring lazyflow RAM limit to 97.7GiB
INFO 2019-07-09 13:48:48,213 memory 31681 140600484841216 Available memory set to 97.7GiB
WARNING 2019-07-09 13:48:49,746 opConservationTracking 31681 140600484841216 Could not find any ILP solver
WARNING 2019-07-09 13:48:49,753 opStructuredTracking 31681 140600484841216 Could not find any ILP solver
WARNING 2019-07-09 13:48:49,754 structuredTrackingWorkflow 31681 140600484841216 Could not find any learning solver. Tracking will use flow-based solver (DPCT). Learning for tracking will be disabled!
INFO 2019-07-09 13:48:50,037 projectManager 31681 140600484841216 Opening Project: full-vol-autocontext_n5.ilp
WARNING 2019-07-09 13:48:50,038 warnings 31681 140600484841216 dataset.py(313): H5pyDeprecationWarning: dataset.value has been deprecated. Use dataset[()] instead.
WARNING 2019-07-09 13:48:50,043 warnings 31681 140600484841216 stype.py(187): UserWarning: ArrayLike.isCompatible: FIXME here
WARNING 2019-07-09 13:48:50,320 warnings 31681 140600484841216 opSimpleBlockedArrayCache.py(43): FutureWarning: Conversion of the second argument of issubdtype from `dtype` to `np.generic` is deprecated. In future, it will be treated as `np.object_ == np.dtype(dtype).type`.
WARNING 2019-07-09 13:48:50,330 warnings 31681 140600484841216 opSlicedBlockedArrayCache.py(141): FutureWarning: Conversion of the second argument of issubdtype from `dtype` to `np.generic` is deprecated. In future, it will be treated as `np.object_ == np.dtype(dtype).type`.
INFO 2019-07-09 13:48:52,087 newAutocontextWorkflow 31681 140600484841216 Beginning Batch Processing
WARNING 2019-07-09 13:48:52,261 warnings 31681 140600484841216 opFormattedDataExport.py(149): UserWarning: The ROI you are attempting to export exceeds the extents of your dataset.  Clipping to dataset bounds.
ERROR 2019-07-09 13:48:55,694 log_exception 31681 140600484841216 Traceback (most recent call last):
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/shell/projectManager.py", line 441, in _loadProject
    self.workflow.onProjectLoaded( self )
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/workflows/newAutocontext/newAutocontextWorkflow.py", line 442, in onProjectLoaded
    self.batchProcessingApplet.run_export_from_parsed_args(self._batch_input_args)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 66, in run_export_from_parsed_args
    return self.run_export(role_path_dict, parsed_args.input_axes, sequence_axis=parsed_args.stack_along)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 131, in run_export
    export_to_array=export_to_array)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 248, in _run_export_with_empty_batch_lane
    assert opDataExportBatchlaneView.ImageToExport.ready()
AssertionError

ERROR 2019-07-09 13:48:55,694 log_exception 31681 140600484841216 Project could not be loaded due to the exception shown above.
Aborting Project Open Action
ERROR 2019-07-09 13:48:55,934 excepthooks 31681 140600484841216 Unhandled exception in thread: 'MainThread'
ERROR 2019-07-09 13:48:55,935 excepthooks 31681 140600484841216 Traceback (most recent call last):
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik.py", line 139, in <module>
    main()
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik.py", line 133, in main
    hShell = ilastik_main.main(parsed_args, workflow_cmdline_args)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik_main.py", line 218, in main
    f(shell)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik_main.py", line 396, in loadProject
    shell.openProjectFile(path, parsed_args.readonly)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/shell/headless/headlessShell.py", line 117, in openProjectFile
    self.projectManager._loadProject(hdf5File, projectFilePath, readOnly)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/lazyflow/lazyflow/utility/timer.py", line 153, in wrapper
    return func(*args, **kwargs)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/shell/projectManager.py", line 441, in _loadProject
    self.workflow.onProjectLoaded( self )
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/workflows/newAutocontext/newAutocontextWorkflow.py", line 442, in onProjectLoaded
    self.batchProcessingApplet.run_export_from_parsed_args(self._batch_input_args)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 66, in run_export_from_parsed_args
    return self.run_export(role_path_dict, parsed_args.input_axes, sequence_axis=parsed_args.stack_along)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 131, in run_export
    export_to_array=export_to_array)
  File "/home/barnesc/.pyenv/versions/anaconda3-2019.03/envs/ilastik2019/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 248, in _run_export_with_empty_batch_lane
    assert opDataExportBatchlaneView.ImageToExport.ready()
AssertionError

Okay, @clbarnes, this just shows you how badly we handle errors in command line parsing.

My guess is that you specify the input data as a positional argument. There is this bug in Python’s argparse that, in short, breaks positional arguments if you have spaces in your options… So my best guess, at the moment is that your command line might work if you replace excised.n5 with --raw_data="excised.n5"

Some combination of using the ilastik “binary” as a base virtualenv (and pip-installing extra dependencies into it), and a brand new project file (recovering the training data from the original was a bit tricky, but manageable), has made this work! From the python end as well.

Thanks for all your help, across various media!

this sounds very adventurous, glad you made it work!

as for the base env, you could have tried using just the ilastik/scripts/devenv.py script specifying your extra dependencies along -p ilastik-dependencies-no-solvers ....

Hey @k-dominik and @clbarnes

I am trying to reproduce this example for pixel classification workflow.

I am a bit stuck at the

DatasetInfo(preloaded_array=input_data)

because I get
TypeError: Can't instantiate abstract class DatasetInfo with abstract methods display_string, legacy_location

Could you advise a workaround?
What are general requirements for passing the data to shell.workflow.batchProcessingApplet.run_export() ?

I haven’t been following ilastik’s development much since this post but I suspect the code sample here is pretty out of date - that’s probably not much help for you, but worth saying for anyone else who comes by it in the future! At the time I heard rumours of some significant refactors being planned on the python side so the process may look a bit different by now.

1 Like

Hi @mpolikarpov,

we’ve refactored that part of the code a bit. If you are only interested in running a pre-trained pixel classfication project on a numpy array, I’d recommend using our experimental API - here’s an example notebook.

If you want the example from above running, have a look at the current example python client (thx to @j.burel for fixing it recently). DatasetInfo is now an abstract base class. For a numpy array you’d now instantiate a PreloadedDatasetInfo. Ideally you’d pass axistags there, too…

the experimental API is a bit easier to use, but currently not does blocking yet. So the whole image is computed at once.

(Hi @clbarnes, thanks for keeping an eye out here, too :))

1 Like

@mpolikarpov
We also have few notebooks using public data stored in IDR if you are interested.
I have a branch tracking the new version of ilastik, I am planning to switch to the new API when it is ready but it does not work yet with the images we use (cf. @k-dominik comments).

Cheers

Jmarie

1 Like

Hi @k-dominik

Thank you so much for the update. API seems quite appealing because of the simplicity.

I am experiencing a bunch of issues for both approaches. Could you advise?


As for python client example that you shared, I try to execute it with the python interpreter, installed by Ilastik, right? In my case it is under

/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/bin

Almost everything goes smooth but I cannot import app

>>> from ilastik import app

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

ImportError: cannot import name 'app' from 'ilastik' (/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik/__init__.py)

All other modules are fine, there are just some messages. Are they ok?

>>> from ilastik.applets.dataSelection import DatasetInfo
/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/lazyflow/lazyflow/classifiers/__init__.py:20: UserWarning: init: Could not import tiktorch classifier
  warnings.warn("init: Could not import tiktorch classifier")
>>> from ilastik.workflows.pixelClassification import PixelClassificationWorkflow
Could not find any ILP solver

For the experimental API, I think I am missing the steps of how to make the dedicated conda environment work and recognise Ilastik. Is there any step-by-step guide?

I am following this link but have problems already at the step of creating an environment. Seems that instructions for python 3.6 are outdated?

And as soon as we are discussing it here:
I was trying to stack tiffs in the subprocess module with something like:

data_list = ["/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00408.tif",
               "/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00409.tif", 
               "/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00410.tif",
               "/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00411.tif"]

subprocess.run(["/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/run_ilastik.sh",
                '--headless',
                '--output_format=hdf5',
                '--output_filename_format=/Users/mpolikarpov/Ilastik_PSI/{nickname}_planetif.h5',
                '--project=/Users/mpolikarpov/Ilastik_PSI/projects/batch_try_080321/pixel_planetif.ilp',
                '--export_source=simple segmentation',
                '--stack_along="z" \ '] + data_list)      

Didn’t work.

I tried from terminal with:

./run_ilastik.sh --headless \
                --project=/Users/mpolikarpov/Ilastik_PSI/projects/batch_try_080321/pixel_planetif.ilp \
                --input_axes=zyx \
                --output_format=hdf5 \
                --output_filename_format=/Users/mpolikarpov/Ilastik_PSI/{nickname}_test2.h5 \
                --raw_data=/Users/mpolikarpov/Ilastik_PSI/test_data/supercut3.tif \
                --stack_along="z" \
                --raw_data="/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00408*.tif" \
                "/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00409*.tif" \
                "/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00410*.tif" \
                "/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00411*.tif"

Didn’t work either. It doesn’t recognise the sequence.

Any formatting error from my side?

Hello @mpolikarpov,

first of all, in order to use the python app in full glory, I’d recommend right now to spin up an ilastik development environment. We’ll add a conda package soon, but right now it’s the way to go. The link you found is unfortunately outdated (thank you for posting it here - I added a note).

Cheers

1 Like

ilastik will require your stack input to be either:

  • something with a glob expression (so * in most cases), or alternatively
  • a file list in a single string separated by the file separator of your operating system (for OSX that’s the colon : character.

so I think your first example should work if you add the following (assuming that the 4 files should be stacked along the ‘z’ axis)

stack_files = ":".join(data_list)
subprocess.run(["/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/run_ilastik.sh",
                '--headless',
                '--output_format=hdf5',
                '--output_filename_format=/Users/mpolikarpov/Ilastik_PSI/{nickname}_planetif.h5',
                '--project=/Users/mpolikarpov/Ilastik_PSI/projects/batch_try_080321/pixel_planetif.ilp',
                '--export_source=simple segmentation',
                '--stack_along="z"',
                stack_files)

In your second examples I see one problem - that --raw_data has been defined twice.
But I think the real problem lies in the specification of the files to stack. How I currently read your example, you want to process 4 individual stacks with the same project. ilastik will find the files for each of your by expanding the * in the file name. As an example, let’s check out the first of the four:

.../data_crop/M277_CF03l_stitched_cropped_00408*.tif:

here, ilastik would look into the data_crop folder and try to find all files, that match this pattern to form a stack out of mutiple files. So it will take the filename until the asterisk (*), so M277_CF03l_stitched_cropped_00408 and find all files that start with this string, have any characters in between, and end with .tif. I’m not sure this is really what you mean. So what glob pattern you use there depends on which files you want to stack, and what other files are present in the folder. A pattern like .../data_crop/M277_CF03l_stitched_cropped_004*.tif for example would match all of the files you have mentioned there, but potentially others that are present in that folder, too.

*note: I’ve shortened paths with ... only for convenience (so the text is shorter).

1 Like

Thanks for the feedback.

In my examples with * above, * is just a typo. I simply try to execute stack processing from the terminal but experience the same issue as from the python shell.

regarding first part with : separator. I tried exactly like you said and like it is written in the manual. I am getting the error

Traceback (most recent call last):
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik.py", line 134, in <module>
    main()
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik.py", line 128, in main
    hShell = ilastik_main.main(parsed_args, workflow_cmdline_args)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik_main.py", line 170, in main
    f(shell)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik_main.py", line 347, in loadProject
    shell.openProjectFile(path, parsed_args.readonly)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik/shell/headless/headlessShell.py", line 123, in openProjectFile
    project_creation_args=project_creation_args,
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik/shell/projectManager.py", line 240, in __init__
    self.workflow = workflowClass(shell, headless, self._workflow_cmdline_args, self._project_creation_args)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/lazyflow/lazyflow/operator.py", line 140, in __call__
    raise RuntimeError(err)
RuntimeError: Could not create instance of '<class 'ilastik.workflows.pixelClassification.pixelClassificationWorkflow.PixelClassificationWorkflow'>'
args   = (<ilastik.shell.headless.headlessShell.HeadlessShell object at 0x7faa608c9898>, True, ['--output_format=hdf5', '--output_filename_format=/Users/mpolikarpov/Ilastik_PSI/{nickname}_planetif_new.h5', '--export_source=simple segmentation', '--stack_along="z"', '/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00408.tif:/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00409.tif:/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00410.tif:/Users/mpolikarpov/Ilastik_PSI/test_data/data_crop/M277_CF03l_stitched_cropped_00411.tif'], [])
kwargs = {}
The exception was:
Could not find one or more input files.  See logged errors.
Traceback:
Traceback (most recent call last):
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/lazyflow/lazyflow/operator.py", line 118, in __call__
    instance = ABCMeta.__call__(cls, *args, **kwargs)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik/workflows/pixelClassification/pixelClassificationWorkflow.py", line 170, in __init__
    self._batch_input_args, unused_args = self.batchProcessingApplet.parse_known_cmdline_args(unused_args)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik/applets/batchProcessing/batchProcessingApplet.py", line 56, in parse_known_cmdline_args
    parsed_args, unused_args = DataSelectionApplet.parse_known_cmdline_args(cmdline_args, self.role_names)
  File "/Applications/ilastik-1.3.3post3-OSX.app/Contents/ilastik-release/ilastik-meta/ilastik/ilastik/applets/dataSelection/dataSelectionApplet.py", line 200, in parse_known_cmdline_args
    raise RuntimeError("Could not find one or more input files.  See logged errors.")
RuntimeError: Could not find one or more input files.  See logged errors.

Executing with a glob expression worked, however I needed to remove the line --stack_along="z" because it was causing errors (although I am sure that my raw data is stacked along z).