NetLogo can be invoked from another Java program and controlled by that program. For example, you might want to call NetLogo from a small program that does something simple like automate a series of model runs.
This section of the User Manual introduces this facility for Java programmers. We'll assume that you know the Java language and related tools and practices.
Note: The controlling facility is considered "experimental". It is likely to continue to change and grow. Code you write now that uses it may need changes in order to continue to work in future NetLogo versions.
The NetLogo API Specification contains further details.
In all of the examples below, when invoking Java to run them, you probably don't want to accept the default heap size settings. Most Java VM's have a very small initial heap size and a small maximum heap size too. When you run the NetLogo application, it uses an initial heap size of 16 megabytes and a maximum heap size of 512 megabytes. This is enough for most models. Here's how to specify the heap sizes on the command line:
java -server -Dsun.java2d.noddraw=true -Xms16M -Xmx512M ...
(Note that we recommend the -server flag for best performance in most situations. We also recommend setting the noddraw option to true when using the GUI as Direct Draw can conflict with OpenGL.)
Here is a small but complete program that starts the full NetLogo application, opens a model, moves a slider, sets the random seed, runs the model for 50 ticks, and then prints a result:
import org.nlogo.app.App; import java.awt.EventQueue; public class Example1 { public static void main(String[] argv) { App.main(argv); try { EventQueue.invokeAndWait ( new Runnable() { public void run() { try { App.app.open ("models/Sample Models/Earth Science/" + "Fire.nlogo"); } catch( java.io.IOException ex ) { ex.printStackTrace(); } } } ); App.app.command("set density 62"); App.app.command("random-seed 0"); App.app.command("setup"); App.app.command("repeat 50 [ go ]"); System.out.println (App.app.report("burned-trees")); } catch(Exception ex) { ex.printStackTrace(); } } }
In order to compile and run this, NetLogo.jar (from the NetLogo distribution) must be in the classpath.
Note the use of EventQueue.invokeAndWait to ensure that a method is called from the right thread. This is because most of the methods on the App class may only be called some certain threads. Most of the methods may only be called from the AWT event queue thread; but a few methods, such as commmand(), may only be called from threads other than the AWT event queue thread (such as, in this example, the main thread).
Rather than continuing to discuss this example in full detail, we refer you to the NetLogo API Specification, which documents all of the ins and outs of the classes and methods used above. Additional methods are available as well.
The example code in this case is very similar to the previous example, but with methods on an instance of the HeadlessWorkspace class substituted for static methods on App.
import org.nlogo.headless.HeadlessWorkspace; public class Example2 { public static void main(String[] argv) { HeadlessWorkspace workspace = new HeadlessWorkspace() ; try { workspace.open ("models/Sample Models/Earth Science/" + "Fire.nlogo"); workspace.command("set density 62"); workspace.command("random-seed 0"); workspace.command("setup"); workspace.command("repeat 50 [ go ]") ; System.out.println (workspace.report("burned-trees")); workspace.dispose(); } catch(Exception ex) { ex.printStackTrace(); } } }
In order to compile and run this, either NetLogo.jar or NetLogoLite.jar (from the NetLogo distribution) must be in your classpath. (The latter jar is smaller, but is only capable of headless operation, not full GUI operation.) When running in a context that does not support a graphical display, the system property java.awt.headless must be true, to force Java to run in headless mode; HeadlessWorkspace automatically sets this property for you.
Since there is no GUI, NetLogo primitives which send output to the command center or output area now go to standard output instead. export-world can still be used to save the model's state. export-view works for writing an image file with a snapshot of the (otherwise invisible) 2D view. The report() method is useful for getting results out of the model and into your Java code.
You can make multiple instances of HeadlessWorkspace and they will operate independently on separate threads without interfering with each other.
When running headless, there are some restrictions:
We plan to lift these restrictions in a future version of NetLogo.
The NetLogo API Specification contains further details.
The Controlling API supports running BehaviorSpace experiments headless. (It does not support running them in BehaviorSpace's GUI, although you can write your own BehaviorSpace-like Java code to run your own BehaviorSpace-like experiments if you want.)
Note that it is definitely not necessary to use the API to do headless BehaviorSpace runs. Headless BehaviorSpace is supported directly from the command line with no Java programming at all required. See the BehaviorSpace Guide for instructions.
In most cases, the command line support will be enough, without needing to use the API. In some situations, though, you may want additional flexibility afforded by the API.
The HeadlessWorkspace has four methods for running experiments: three variants of runExperiment, plus runExperimentFromModel.
runExperimentFromModel is used when the experiment setup is already stored in the model file.
The two forms of runExperiment that take File arguments are used when the experiment setup is stored in a standalone XML file, separate from the model file. If the file contains only one setup, you only need to pass in the File object. If the file contains multiple setups, you must also pass in a String object holding the experiment name.
The form of runExperiment that takes only a String argument (and an argument to specify the output format) is used to pass the XML for the experiment setup directly.
All of these methods take a PrintWriter as a destination for the results. If you just want to send them to standard output, you can pass new java.io.PrintWriter( System.out ).
The BehaviorSpace Guide explains how to specify experiment setups in XML.
The NetLogo API Specification contains further details on the HeadlessWorkspace class and its methods.
When your program controls NetLogo using the App class, the entire NetLogo application is present, including tabs, menubar, and so forth. This arrangement is suitable for controlling or "scripting" a NetLogo model, but not ideal for embedding a NetLogo model in a larger application.
We also have a separate, similar API which allows embedding only parts of NetLogo, such as only the tabs (not the whole window), or only the contents of the Interface tab. At present, this additional API is not documented. If you are interested in using it, please contact us at feedback@ccl.northwestern.edu.
Don't forget to consult the NetLogo API Specification for full details on these classes and methods.
As mentioned before, the controlling facility is considered experimental. This initial API doesn't necessarily include everything you might expect. Some facilities exist, but are not yet documented. So if you don't see the capability you want, contact us; we may be able to help you do you what you want. Please do not hesitate to contact us at feedback@ccl.northwestern.edu with questions, as we may be able to find a workaround or provide additional guidance where our documentation is thin.