Developer documentation

Using JIPipe in Java

The JIPipe API allows you to run algorithms, graphs, and projects in a pure Java environment without the need for a GUI or through ImageJ1 or ImageJ2 scripts.

Prerequisites

To use the JIPipe API JIPipe must be initialized first. This requires an ImageJ instance or any other way to load SciJava plugins. The following example shows how to initialize JIPipe manually from a main function.

public static void main(String[] args) {
  // Just call this function before all others. It will create a new ImageJ instance and passes the context to JIPipe
  // If JIPipe is already initialized, the function has no effect
  JIPipe.ensureInstance();

  // If you already have a Context object: JIPipe.ensureInstance(context)

  // JIPipe is now ready to use
}

Loading and running a project

You can load a JIPipeProject via a static method. Running the project either involves enqueuing a JIPipeProjectRun into the JIPipeRunnerQueue or running it on the current thread. The run has a multitude of JIPipeRunSettings that control how/if output is written or how many threads are used.

public static void main(String[] args) {
  // First initialize JIPipe before this line!

  // Load the project
  // JIPipe will put any non-exception errors or warnings into the report
  JIPipeValidityReport report = new JIPipeValidityReport();
  JIPipeProject project = JIPipeProject.loadProject(Paths.get("my-project.jip"), report);

  // Create a run that generates a deep-copy of the project's graph
  // The run is controlled by the JIPipeRunSettings instance that allows you to
  // have runs without caching or writing outputs if needed
  JIPipeRunSettings settings = new JIPipeRunSettings();
  settings.setOutputPath(Paths.get("/data/my-project-output"));
  JIPipeRun run = new JIPipeRun(project, settings);

  // Option 1: Run in separate thread (Async)
  JIPipeRunnerQueue.getInstance().enqueue(run);

  // Option 2: Run it on the current thread
  // The run itself has a property getProgressInfo() that allows access to the progress & log
  run.run();
}

Loading a result

To load an existing result folder, the JIPipeProjectRun is imported back into JIPipe. The run itself contains a JIPipeGraph instance with nodes that are aware of the data storage location. The storage location contains a data-table.json file that can be imported as JIPipeDataTable.

  public static void main(String[] args) {
    // First initialize JIPipe before this line!

    // Load the run
    // It will load the project as well
    Path path = Paths.get("/data/my-project-output");
    JIPipeRun run = JIPipeRun.loadFromFolder(path, report);
    run.getProject().setWorkDirectory(path);

    // You can now access the run's graph and access the data slots
    JIPipeDataSlot slot = run.getGraph().findNode("UUID or alias ID").getOutputSlot("Output");

    // Load the slot's data table
    JIPipeDataTable data = JIPipeDataTable.importData(new JIPipeFileSystemReadDataStorage(slot.getSlotStoragePath()), new JIPipeProgressInfo());

    // Work with the data
  }

Building and running a graph

JIPipe allows to create and run JIPipeGraph objects without involving a project. A simple JIPipeGraphRunner is available to execute a graph.

  public static void main(String[] args) {
    JIPipe.ensureInstance();
    // First initialize JIPipe before this line!

    JIPipeGraph graph = new JIPipeGraph();

    // There are multiple ways to instantiate a new node:

    // Option 1: Utility function
    JIPipeGraphNode first = JIPipe.createNode("import-file", JIPipeGraphNode.class);

    // Option 2: Using the registry
    JIPipeGraphNode second = JIPipeNodeRegistry.getInstance().getInfoById("import-imagej-imgplus-from-file").newInstance();


    // Add the nodes into the graph and connect them
    graph.insertNode(first);
    graph.insertNode(second);
    graph.connect(first.getOutputSlot("Output"), second.getInputSlot("Input"), true);


    // Use the graph runner
    // We always recommend to make a copy of the graph if it is used somewhere else
    JIPipeGraphRunner run = new JIPipeGraphRunner(new JIPipeGraph(graph));

    // Option 1: Run in separate thread (Async)
    JIPipeRunnerQueue.getInstance().enqueue(run);

    // Option 2: Run it on the current thread
    // The run itself has a property getProgressInfo() that allows access to the progress & log
    run.run();
  }

Running a single node

You can run single algorithm nodes without involving a project or a graph:

public static void main(String[] args) {
  // First initialize JIPipe before this line!

  JIPipeSimpleIteratingAlgorithm node = JIPipe.createNode("import-imagej-imgplus-from-file", JIPipeSimpleIteratingAlgorithm.class);

  // The node requires a progress info 
  JIPipeProgressInfo progress = new JIPipeProgressInfo();

  // Always clear the node first (allows you to re-use it)
  node.clearSlotData();

  // Add inputs
  node.getFirstInputSlot().addData(new FileData(Paths.get("/data/image.tif")), progress);

  // Run the node
  node.run(progress);

  // Extract the output
  ImagePlusData image = node.getFirstOutputSlot().getData(0, ImagePlusData.class, progress);
}