alerone
alerone

Reputation: 21

How to Run NetLogo Headless Without a Pre-Existing .nlogo File (Starting from .nls File)?

I would like to set up a fully headless NetLogo workflow, that doesn't require me to open the GUI to create the initial .nlogo file. Everything I've been able to find through searching requires a .nlogo file to already exist as created by the GUI. Is it possible to create a .nlogo file from a .nls file without a GUI? Or to run headless mode just from the .nls without a .nlogo file? I am using OpenJDK 11 and NetLogo 6.4.0 on Mac OS Sonoma.

I have looked at the BehaviorSpace documentation, but all the headless examples use pre-existing .nlogo files.

I tried to create a minimal example using a .nls file and a .java file:

minimal.nls (runs correctly when plugged into the GUI):

globals []

to go
  print "Hello World!"
  tick
end

Minimal.java:

import org.nlogo.headless.HeadlessWorkspace;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.io.IOException;

public class Minimal {
    public static void main(String[] args) {
        HeadlessWorkspace workspace = HeadlessWorkspace.newInstance();
        try {
            // Read NetLogo code from the file
            String netlogoCode = new String(Files.readAllBytes(Paths.get("minimal.nls")), StandardCharsets.UTF_8);

            // Print the NetLogo code for verification
            System.out.println("NetLogo code:");
            System.out.println(netlogoCode);

            // Open the workspace
            try {
                workspace.openString(netlogoCode);
                System.out.println("NetLogo code loaded successfully.");
            } catch (Exception e) {
                System.err.println("Error loading NetLogo code:");
                e.printStackTrace();
                System.exit(1);
            }

            // Run the simulation
            try {
                workspace.command("go");
                System.out.println("Simulation ran successfully.");
            } catch (Exception e) {
                System.err.println("Error running 'go' command:");
                e.printStackTrace();
                System.exit(1);
            }

        } catch (IOException ex) {
            System.err.println("An error occurred while reading the NetLogo file:");
            ex.printStackTrace();
            System.exit(1);
        } finally {
            // Close the workspace and handle InterruptedException
            try {
                workspace.dispose();
            } catch (InterruptedException e) {
                e.printStackTrace();
                // Optionally, restore the interrupted status
                Thread.currentThread().interrupt();
            }
        }
    }
}

Expected result:

NetLogo code:
globals []

to go
  print "Hello World!"
  tick
end

NetLogo code loaded successfully.
Hello world!
Simulation ran successfully.

Actual result:

NetLogo code:
globals []

to go
  print "Hello World!"
  tick
end

NetLogo code loaded successfully.
Error running 'go' command:
Nothing named GO has been defined. at position 33 in
    at org.nlogo.core.Fail$.exception(Fail.scala:27)
    at org.nlogo.core.Fail$.exception(Fail.scala:25)
    at org.nlogo.core.Fail$.exception(Fail.scala:23)
    at org.nlogo.parse.ExpressionParser$.parseStatement(ExpressionParser.scala:151)
    at org.nlogo.parse.ExpressionParser$.$anonfun$apply$1(ExpressionParser.scala:32)
    at org.nlogo.parse.ExpressionParser$.parseStatements(ExpressionParser.scala:44)
    at org.nlogo.parse.ExpressionParser$.apply(ExpressionParser.scala:32)
    at org.nlogo.parse.NetLogoParser.parseProcedure(NetLogoParser.scala:47)
    at org.nlogo.parse.NetLogoParser.parseProcedure$(NetLogoParser.scala:29)
    at org.nlogo.parse.FrontEnd$.parseProcedure(FrontEnd.scala:10)
    at org.nlogo.parse.NetLogoParser.$anonfun$basicParse$1(NetLogoParser.scala:25)
    at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:286)
    at scala.collection.Iterator.foreach(Iterator.scala:943)
    at scala.collection.Iterator.foreach$(Iterator.scala:943)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
    at scala.collection.MapLike$DefaultValuesIterable.foreach(MapLike.scala:214)
    at scala.collection.TraversableLike.map(TraversableLike.scala:286)
    at scala.collection.TraversableLike.map$(TraversableLike.scala:279)
    at scala.collection.AbstractTraversable.map(Traversable.scala:108)
    at org.nlogo.parse.NetLogoParser.basicParse(NetLogoParser.scala:25)
    at org.nlogo.parse.NetLogoParser.basicParse$(NetLogoParser.scala:15)
    at org.nlogo.parse.FrontEnd$.basicParse(FrontEnd.scala:10)
    at org.nlogo.parse.FrontEndMain.frontEnd(FrontEnd.scala:26)
    at org.nlogo.parse.FrontEndMain.frontEnd$(FrontEnd.scala:25)
    at org.nlogo.parse.FrontEnd$.frontEnd(FrontEnd.scala:10)
    at org.nlogo.compile.CompilerMain$.compile(CompilerMain.scala:47)
    at org.nlogo.compile.Compiler.compileMoreCode(Compiler.scala:85)
    at org.nlogo.compile.Compiler.compileMoreCode(Compiler.scala:100)
    at org.nlogo.workspace.Evaluator.invokeCompiler(Evaluator.scala:160)
    at org.nlogo.workspace.Evaluator.evaluateCommands(Evaluator.scala:20)
    at org.nlogo.workspace.Evaluating.command(Evaluating.scala:80)
    at org.nlogo.workspace.Evaluating.command$(Evaluating.scala:79)
    at org.nlogo.workspace.AbstractWorkspaceScala.command(AbstractWorkspaceScala.scala:25)
    at Minimal.main(Minimal.java:30)

How can I run a NetLogo model in headless mode starting from a .nls file or source code without needing to create a .nlogo file in the GUI? Am I doing something wrong, or does this functionality not exist/do I have to use the GUI to create the model file?

Upvotes: 2

Views: 64

Answers (0)

Related Questions