### Initialize NetLogo Link and Load Model Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Establishes a connection to NetLogo, loads a specified model, and executes the initial 'setup' command. Requires NetLogo to be installed and accessible. ```python %matplotlib inline import pandas as pd import matplotlib.pyplot as plt import seaborn as sns sns.set_style("white") sns.set_context("talk") import pynetlogo netlogo = pynetlogo.NetLogoLink( gui=True, ) netlogo.load_model("./models/Wolf Sheep Predation_v6.nlogo") netlogo.command("setup") ``` -------------------------------- ### Import SALib Sampling and Analysis Modules Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Imports necessary modules from SALib for Sobol sensitivity analysis. Ensure SALib is installed. ```python from SALib.sample import sobol as sobol_sample from SALib.analyze import sobol ``` -------------------------------- ### Start Java Virtual Machine (JVM) Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Initialize the Java Virtual Machine with a specified JVM path and the collected JARs in the classpath. This is essential before interacting with Java objects. ```python jvm_path = "/Users/jhkwakkel/Downloads/jdk-19.0.2.jdk/Contents/MacOS/libjli.dylib" jpype.startJVM(jvm_path, classpath=jars) ``` -------------------------------- ### Setting up Parallel Execution Environment with %%px Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb The `%%px` magic command executes notebook cells on all engines. This example includes necessary imports and model loading for parallel NetLogo simulations. ```python %%px import os os.chdir(cwd) # pushed to all workers via direct_View.push import pynetlogo import pandas as pd netlogo = pynetlogo.NetLogoLink(gui=False) netlogo.load_model('./models/Wolf Sheep Predation_v6.nlogo') ``` -------------------------------- ### Instantiate NetLogoLink Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Create an instance of the NetLogoLink class to establish a connection with NetLogo. Note: This example demonstrates a NameError due to an undefined variable 'gui'. ```python link = NetLogoLink(jpype.java.lang.Boolean(False), jpype.java.lang.Boolean(thd)) ``` -------------------------------- ### Run NetLogo Commands and Report Values Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Executes NetLogo commands such as 'setup' and 'go', and reports the count of sheep. It also demonstrates reporting a value repeatedly until a condition is met. ```python netlogo.command("setup") print(netlogo.report("count sheep")) netlogo.report_while("count sheep", "count sheep >= 100", max_seconds=5) ``` -------------------------------- ### Import Libraries for NetLogo-SALib Interaction Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Imports necessary Python libraries for data manipulation, plotting, and pyNetLogo integration. Ensure these libraries are installed. ```python %matplotlib inline import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import pyNetLogo ``` -------------------------------- ### Initialize ipyparallel Cluster Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Initializes and starts an ipyparallel cluster with a specified number of engines. This is required for parallel execution. ```python import ipyparallel as ipp cluster = ipp.Cluster(n=4) cluster.start_cluster_sync() ``` -------------------------------- ### Find NetLogo Home Directory (macOS) Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Locate the NetLogo installation directory on macOS using PyNetLogo's utility function. This is a prerequisite for finding necessary JAR files. ```python netlogo_home = pynetlogo.core.find_netlogo_mac() netlogo_home ``` -------------------------------- ### Run Simulation Ticks and Plot Agent Energy Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Executes the NetLogo simulation for a specified number of ticks (100 in this example) using either `command` or `repeat_command`. It also prepares to return agent energy values for histogram plotting. ```python # We can use either of the following commands to run for 100 ticks: netlogo.command("repeat 100 [go]") # netlogo.repeat_command('go', 100) ``` -------------------------------- ### Example Usage of plot_sobol_indices Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Demonstrates how to use the plot_sobol_indices function with sample data. Sets the figure size and displays the plot. Requires seaborn for styling. ```python sns.set_style("whitegrid") fig = plot_sobol_indices(Si, criterion="ST", threshold=0.005) fig.set_size_inches(7, 7) plt.show() ``` -------------------------------- ### Get Direct View of Engines Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Obtains a direct view of all engines in the ipyparallel cluster, allowing for direct interaction with each engine. ```python direct_view = rc[:] ``` -------------------------------- ### Export Patch Data and Update NetLogo Environment Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Export patch data to an Excel file using Pandas and update the NetLogo environment with new patch values using `patch_set`. This example inverts the 'countdown' values. ```python countdown_df.to_excel("countdown.xlsx") netlogo.patch_set("countdown", countdown_df.max() - countdown_df) ``` -------------------------------- ### Get NetLogoLink Java Class Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Retrieve the Java class for NetLogo communication using JPype. This class is used to establish a link with NetLogo. ```python jpype.JClass("netLogoLink.NetLogoLink") ``` -------------------------------- ### JPype startJVM Signature and Docstring Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Displays the signature and documentation for the `jpype.startJVM` function, detailing its parameters, keyword arguments, and potential exceptions. Useful for understanding how to configure JVM startup. ```python ?jpype.startJVM ``` -------------------------------- ### Initialize NetLogo Instance Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Initializes a NetLogo instance. This is the first step before interacting with any NetLogo models. ```python netlogo = NetLogo(model_path='model.xml') ``` -------------------------------- ### Setting up Parallel Environment with %%px Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb The `%%px` magic command executes a notebook cell on all parallel engines. It's used here to set up the necessary imports and load the NetLogo model on each engine. ```python %%px import os os.chdir(cwd) import pyNetLogo import pandas as pd netlogo = pyNetLogo.NetLogoLink(gui=False) netlogo.load_model('./models/Wolf Sheep Predation_v6.nlogo') ``` -------------------------------- ### Run Sequential Simulations and Collect Results Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Iterates through each parameter set generated by SALib, sets NetLogo global variables, runs the model for 100 ticks using repeat_report, and calculates the mean counts of sheep and wolves. Also tracks elapsed runtime. ```python import time t0 = time.time() for run in range(param_values.shape[0]): # Set the input parameters for i, name in enumerate(problem["names"]): if name == "random-seed": # The NetLogo random seed requires a different syntax netlogo.command("random-seed {}".format(param_values[run, i])) else: # Otherwise, assume the input parameters are global variables netlogo.command("set {0} {1}".format(name, param_values[run, i])) netlogo.command("setup") # Run for 100 ticks and return the number of sheep and wolf agents at each time step counts = netlogo.repeat_report(["count sheep", "count wolves"], 100) # For each run, save the mean value of the agent counts over time results.loc[run, "Avg. sheep"] = np.mean(counts["count sheep"]) results.loc[run, "Avg. wolves"] = np.mean(counts["count wolves"]) elapsed = time.time() - t0 # Elapsed runtime in seconds ``` -------------------------------- ### Create NetLogo Link JAR Source: https://github.com/quaquel/pynetlogo/blob/master/src/pynetlogo/java/readme.md Use this command to create a NetLogo link JAR file. Ensure the NetLogo JAR for the specific version is on the build path. ```bash jar cfv netlogolink63.jar * ``` -------------------------------- ### Setting up Direct View for Engines Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Creates a direct view to access all engines in the ipyparallel cluster, enabling parallel execution of tasks. ```python direct_view = client[:] ``` -------------------------------- ### Initialize NetLogo Link and Load Model Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Initializes a pyNetLogo Link object in headless mode and loads the specified NetLogo model. Ensure the model file path is correct. ```python netlogo = pynetlogo.NetLogoLink(gui=False) netlogo.load_model("./models/Wolf Sheep Predation_v6.nlogo") ``` -------------------------------- ### Initialize and Load NetLogo Model Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Initializes a PyNetLogo link to a NetLogo instance without the GUI and loads a specified NetLogo model file. ```python import os netlogo = pyNetLogo.NetLogoLink(gui=False) model_file = os.path.join( netlogo.netlogo_home, "models/Sample Models/Biology/Wolf Sheep Predation.nlogo" ) netlogo.load_model(model_file) ``` -------------------------------- ### Generating Sobol Samples with SALib Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Generates experimental design samples using the Saltelli sampler from SALib for a Sobol analysis. The sample size is determined by the problem definition and a base sample number 'n'. ```python n = 1000 param_values = saltelli.sample(problem, n, calc_second_order=True) ``` -------------------------------- ### Import Libraries for Sensitivity Analysis Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Imports necessary libraries for numerical operations, plotting, and sensitivity analysis with SALib and pyNetLogo. ```python import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns sns.set_style("white") sns.set_context("talk") import pynetlogo # Import the sampling and analysis modules for a Sobol variance-based # sensitivity analysis from SALib.sample import sobol as sobolsample from SALib.analyze import sobol ``` -------------------------------- ### Import PyNetLogo Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Import the PyNetLogo library for NetLogo integration. ```python import pynetlogo ``` -------------------------------- ### Run NetLogo Simulations Sequentially Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Iterates through each parameter set, sets NetLogo global variables, runs the model, and collects average agent counts. Records the elapsed time for the entire process. ```python import time t0 = time.time() for run in range(param_values.shape[0]): # Set the input parameters for i, name in enumerate(problem["names"]): if name == "random-seed": # The NetLogo random seed requires a different syntax netlogo.command("random-seed {}".format(param_values[run, i])) else: # Otherwise, assume the input parameters are global variables netlogo.command("set {0} {1}".format(name, param_values[run, i])) netlogo.command("setup") # Run for 100 ticks and return the number of sheep and wolf agents at each time step counts = netlogo.repeat_report(["count sheep", "count wolves"], 100, include_t0=False) # For each run, save the mean value of the agent counts over time results.loc[run, "Avg. sheep"] = counts["count sheep"].values.mean() results.loc[run, "Avg. wolves"] = counts["count wolves"].values.mean() elapsed = time.time() - t0 # Elapsed runtime in seconds ``` -------------------------------- ### Initialize Results DataFrame Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Creates an empty Pandas DataFrame to store the simulation results, with columns for average sheep and wolf counts. ```python results = pd.DataFrame(columns=["Avg. sheep", "Avg. wolves"]) ``` -------------------------------- ### Generate Sobol Samples Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Generates samples for Sobol sensitivity analysis using the defined problem and a baseline sample size 'n'. Set calc_second_order=True for second-order indices. The sample size will be n*(2p+2). ```python n = 1024 param_values = sobol_sample.sample(problem, n, calc_second_order=True) ``` -------------------------------- ### Running Simulations with Load Balanced View Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Utilize `rc.load_balanced_view()` and `lview.map_sync` to distribute the `simulation` function across experiments. This method efficiently handles simulations of varying durations. ```python lview = rc.load_balanced_view() results = pd.DataFrame(lview.map_sync(simulation, param_values)) ``` -------------------------------- ### command(netlogo_command: str) Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Execute the supplied command in NetLogo. ```APIDOC #### command(netlogo_command: str) Execute the supplied command in NetLogo. * **Parameters:** **netlogo_command** (*str*) – Valid NetLogo command * **Raises:** [**NetLogoException**](#pynetlogo.core.NetLogoException) – If a LogoException or CompilerException is raised by NetLogo ``` -------------------------------- ### Run NetLogo Command from Python Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Executes a NetLogo command string. Ensure the command is valid NetLogo syntax. ```python netlogo.link.sourceFromString(command, True) ``` -------------------------------- ### Running Simulations with Load Balanced View Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Utilizes `client.load_balanced_view()` and `map_sync` to distribute the `simulation` function across multiple engines. This method efficiently handles tasks with varying execution times. ```python lview = client.load_balanced_view() results = pd.DataFrame(lview.map_sync(simulation, param_values)) ``` -------------------------------- ### load_model(path: str) Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Load a NetLogo model. ```APIDOC #### load_model(path: str) Load a NetLogo model. * **Parameters:** **path** (*str*) – Path to the NetLogo model * **Raises:** * **FileNotFoundError** – in case path does not exist * [**NetLogoException**](#pynetlogo.core.NetLogoException) – In case of a NetLogo exception ``` -------------------------------- ### Set Headless Mode for JVM Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Configure the Java Virtual Machine to run in headless mode, which is useful for environments without a graphical display. This prevents AWT-related errors. ```python jpype.java.lang.System.setProperty("java.awt.headless", "true") ``` -------------------------------- ### Visualize Output Distributions with Histograms Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Generates histograms to visualize the distribution of model outputs for each outcome. Requires matplotlib and pandas. ```python fig, ax = plt.subplots(1, len(results.columns), sharey=True) for i, n in enumerate(results.columns): ax[i].hist(results[n], 20) ax[i].set_xlabel(n) ax[0].set_ylabel("Counts") fig.set_size_inches(10, 4) fig.subplots_adjust(wspace=0.1) plt.show() ``` -------------------------------- ### repeat_command(netlogo_command: str, reps: int) Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Execute the supplied command in NetLogo a given number of times. ```APIDOC #### repeat_command(netlogo_command: str, reps: int) Execute the supplied command in NetLogo a given number of times. * **Parameters:** * **netlogo_command** (*str*) – Valid NetLogo command * **reps** (*int*) – Number of repetitions for which to repeat commands * **Raises:** [**NetLogoException**](#pynetlogo.core.NetLogoException) – If a LogoException or CompilerException is raised by NetLogo ``` -------------------------------- ### Generate Sobol Sample Values Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Generates sample values using SALib's Sobol sampler for a given problem definition and baseline sample size. This is used for variance-based sensitivity analysis. ```python n = 1024 param_values = sobolsample.sample(problem, n, calc_second_order=True) ``` -------------------------------- ### Parallel NetLogo Simulation with Multiprocessing Pool Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_multiprocessing.ipynb Initializes and runs NetLogo simulations in parallel using `multiprocessing.Pool`. Ensure the NetLogo model file path is correct and the model is compatible. ```python from multiprocessing import Pool import os import pandas as pd import pyNetLogo from SALib.sample import saltelli def initializer(modelfile): """initialize a subprocess Parameters ---------- modelfile : str """ # we need to set the instantiated netlogo # link as a global so run_simulation can # use it global netlogo netlogo = pyNetLogo.NetLogoLink(gui=False) netlogo.load_model(modelfile) def run_simulation(experiment): """run a netlogo model Parameters ---------- experiments : dict """ # Set the input parameters for key, value in experiment.items(): if key == "random-seed": # The NetLogo random seed requires a different syntax netlogo.command("random-seed {}".format(value)) else: # Otherwise, assume the input parameters are global variables netlogo.command("set {0} {1}".format(key, value)) netlogo.command("setup") # Run for 100 ticks and return the number of sheep and # wolf agents at each time step counts = netlogo.repeat_report(["count sheep", "count wolves"], 100) results = pd.Series( [counts["count sheep"].values.mean(), counts["count wolves"].values.mean()], index=["Avg. sheep", "Avg. wolves"], ) return results modelfile = os.path.abspath("./models/Wolf Sheep Predation_v6.nlogo") problem = { "num_vars": 6, "names": [ "random-seed", "grass-regrowth-time", "sheep-gain-from-food", "wolf-gain-from-food", "sheep-reproduce", "wolf-reproduce", ], "bounds": [ [1, 100000], [20.0, 40.0], [2.0, 8.0], [16.0, 32.0], [2.0, 8.0], [2.0, 8.0], ], } n = 10 param_values = saltelli.sample(problem, n, calc_second_order=True) # cast the param_values to a dataframe to # include the column labels experiments = pd.DataFrame(param_values, columns=problem["names"]) with Pool(initializer=initializer, initargs=(modelfile,)) as executor: results = [] for entry in executor.map(run_simulation, experiments.to_dict("records")): results.append(entry) results = pd.DataFrame(results) ``` -------------------------------- ### Handle NetLogoException in Python Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Demonstrates how to catch and handle a NetLogoException, which is raised for undefined variables or errors during NetLogo execution. The exception message provides details about the error. ```python raise NetLogoException(str(ex)) ``` -------------------------------- ### Displaying First 5 Rows of Results Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb View the initial rows of the results DataFrame to quickly inspect the output of the parallel simulations. ```python results.head(5) ``` -------------------------------- ### Importing Libraries for Analysis Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Imports essential Python libraries for data manipulation, plotting, and interaction with NetLogo. ```python %matplotlib inline import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import pynetlogo ``` -------------------------------- ### Advanced Visualization for Second-Order Interactions Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Sets up plotting functions for visualizing second-order interactions between inputs using SALib's Sobol indices. This snippet includes helper functions for normalization and plotting circles, and a filter function for selecting data based on criteria. ```python %matplotlib inline import itertools from math import pi def normalize(x, xmin, xmax): return (x - xmin) / (xmax - xmin) def plot_circles(ax, locs, names, max_s, stats, smax, smin, fc, ec, lw, zorder): s = np.asarray([stats[name] for name in names]) s = 0.01 + max_s * np.sqrt(normalize(s, smin, smax)) fill = True for loc, name, si in zip(locs, names, s): if fc == "w": fill = False else: ec = "none" x = np.cos(loc) y = np.sin(loc) circle = plt.Circle( (x, y), radius=si, ec=ec, fc=fc, transform=ax.transData._b, zorder=zorder, lw=lw, fill=True, ) ax.add_artist(circle) def filter(sobol_indices, names, locs, criterion, threshold): if criterion in ["ST", "S1", "S2"]: data = sobol_indices[criterion] data = np.abs(data) data = data.flatten() # flatten in case of S2 # TODO:: remove nans ``` -------------------------------- ### Connect to ipyparallel Cluster Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Connects to the running ipyparallel cluster by creating a client and ensuring all engines are available. ```python rc = cluster.connect_client_sync() rc.wait_for_engines(n=4) rc.ids ``` -------------------------------- ### Pushing Variables to Engines with IPyparallel Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Use `direct_view.push` to make notebook variables available on all parallel engines. Ensure the `block=True` argument for synchronous execution. ```python direct_view.push(dict(problem=problem), block=True) ``` -------------------------------- ### Save Results to CSV Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Saves the collected simulation results to a CSV file named 'Sobol_sequential.csv'. ```python results.to_csv("Sobol_sequential.csv") ``` -------------------------------- ### Connecting to ipyparallel Cluster Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Instantiates an ipyparallel client to connect to a running ipcluster controller and its engines. Verifies the number of available engines. ```python import ipyparallel client = ipyparallel.Client() client.ids ``` -------------------------------- ### Import JPype Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Import the JPype library to enable Java-Python interoperability. ```python import jpype ``` -------------------------------- ### Import NetLogoLink Class Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Import the NetLogoLink class directly from the Java package for easier use in Python. ```python from netLogoLink import NetLogoLink ``` -------------------------------- ### Find NetLogo JARs Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Identify the required Java Archive (JAR) files for NetLogo integration. This function requires the NetLogo home directory. ```python jars = pynetlogo.core.find_jars(netlogo_home) ``` -------------------------------- ### kill_workspace() Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Close NetLogo and shut down the JVM. ```APIDOC #### kill_workspace() Close NetLogo and shut down the JVM. ``` -------------------------------- ### Pushing Variables to Engines Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Use `direct_view.push` to make notebook variables available on the parallel engines. This is useful for sharing simulation parameters or configurations. ```python direct_view.push(dict(problem=problem)) ``` -------------------------------- ### Read Results from CSV Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Loads simulation results from the 'Sobol_sequential.csv' file back into a Pandas DataFrame. ```python results = pd.read_csv("Sobol_sequential.csv", header=0, index_col=0) ``` -------------------------------- ### Display Elapsed Runtime Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Prints the total time taken to complete all sequential simulations. ```python elapsed ``` -------------------------------- ### Python 2/3 Compatibility Imports Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Ensures compatibility with both Python 2 and Python 3 by conditionally importing `izip`. ```python # Ensuring compliance of code with both python2 and python3 from __future__ import division, print_function try: from itertools import izip as zip except ImportError: # will be 3.x series pass ``` -------------------------------- ### Define Problem for SALib Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Defines the problem dictionary for SALib, specifying the number of variables, their names, and their bounds for sensitivity analysis. ```python problem = { "num_vars": 6, "names": [ "random-seed", "grass-regrowth-time", "sheep-gain-from-food", "wolf-gain-from-food", "sheep-reproduce", "wolf-reproduce", ], "bounds": [ [1, 100000], [20.0, 40.0], [2.0, 8.0], [16.0, 32.0], [2.0, 8.0], [2.0, 8.0], ], } ``` -------------------------------- ### Calculate Sobol Indices Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Calculates first-order (S1), second-order (S2), and total (ST) Sobol indices to estimate input contributions to output variance and input interactions. Requires SALib. ```python Si = sobol.analyze( problem, results["Avg. sheep"].values, calc_second_order=True, print_to_console=False, ) ``` -------------------------------- ### report(netlogo_reporter: str) Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Return values from a NetLogo reporter. ```APIDOC #### report(netlogo_reporter: str) Return values from a NetLogo reporter. Any reporter (command which returns a value) that can be called in the NetLogo Command Center can be called with this method. * **Parameters:** **netlogo_reporter** (*str*) – Valid NetLogo reporter * **Raises:** [**NetLogoException**](#pynetlogo.core.NetLogoException) – If a LogoException or CompilerException is raised by NetLogo ``` -------------------------------- ### Visualize Output Distributions Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Generates histograms for each outcome variable (Avg. sheep, Avg. wolves) to visualize their distributions. Uses Seaborn for styling. ```python sns.set_style("white") sns.set_context("talk") fig, ax = plt.subplots(1, len(results.columns), sharey=True) for i, n in enumerate(results.columns): ax[i].hist(results[n], 20) ax[i].set_xlabel(n) ax[0].set_ylabel("Counts") fig.set_size_inches(10, 4) fig.subplots_adjust(wspace=0.1) plt.show() ``` -------------------------------- ### Add Custom JAR to Classpath Source: https://github.com/quaquel/pynetlogo/blob/master/tests/Untitled.ipynb Append a custom JAR file to the list of JARs to be used by the Java Virtual Machine. Ensure the path to the JAR is absolute. ```python import os jars.append(os.path.abspath("test.jar")) ``` -------------------------------- ### Load Agent Data from Excel Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Loads agent initial properties, including 'who', 'xcor', and 'ycor', from an Excel file into a Pandas DataFrame. This prepares data for updating agent states in NetLogo. ```python agent_xy = pd.read_excel("./data/xy_DataFrame.xlsx") agent_xy[["who", "xcor", "ycor"]].head(5) ``` -------------------------------- ### Push Current Working Directory to Engines Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Pushes the current working directory of the notebook to a 'cwd' variable on all engines. This ensures consistency in file paths across the cluster. ```python import os # Push the current working directory of the notebook to a "cwd" variable on the engines that can be accessed later direct_view.push(dict(cwd=os.getcwd()), block=True) ``` -------------------------------- ### NetLogoLink Class Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md The NetLogoLink class is the main interface for interacting with NetLogo. It allows you to create a link to a NetLogo instance, load models, execute commands, and retrieve data. ```APIDOC ## class pynetlogo.core.NetLogoLink(gui: bool = False, thd: bool = False, netlogo_home: str | None = None, jvm_path: str | None = None, jvm_args: list[str] | None = None) Create a link with NetLogo. Underneath, the NetLogo JVM is started through Jpype. If netlogo_home, netlogo_version, or jvm_home are not provided, the link will try to identify the correct parameters automatically on Mac or Windows. netlogo_home and netlogo_version are required on Linux. * **Parameters:** * **gui** (*bool* *,* *optional*) – If true, displays the NetLogo GUI (not supported on Mac) * **thd** (*bool* *,* *optional*) – If true, use NetLogo 3D * **netlogo_home** (*str* *,* *optional*) – Path to the NetLogo installation directory (required on Linux) * **jvm_path** (*str* *,* *optional*) – path of the jvm * **jvm_args** (*list* *of* *str* *,* *optional*) – additional arguments that should be used when starting the jvm ``` -------------------------------- ### Visualize Parameter-Output Relationships with Scatter Plots Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Generates bivariate scatter plots for each input parameter against a specific output. Uses scipy to calculate Pearson correlation coefficients and annotates each plot with the 'r' value. Ensure 'seaborn' and 'matplotlib' are imported. ```python import scipy nrow = 2 col = 3 fig, ax = plt.subplots(nrow, ncol, sharey=True) sns.set_context("talk") y = results["Avg. sheep"] for i, a in enumerate(ax.flatten()): x = param_values[:, i] sns.regplot( x=x, y=y, ax=a, ci=None, color="k", scatter_kws={"alpha": 0.2, "s": 4, "color": "gray"}, ) pearson = scipy.stats.pearsonr(x, y) a.annotate( "r: {:6.3f}".format(pearson[0]), xy=(0.15, 0.85), xycoords="axes fraction", fontsize=13, ) if divmod(i, ncol)[1] > 0: a.get_yaxis().set_visible(False) a.set_xlabel(problem["names"][i]) a.set_ylim([0, 1.1 * np.max(y)]) fig.set_size_inches(9, 9, forward=True) fig.subplots_adjust(wspace=0.2, hspace=0.3) # plt.savefig('JASSS figures/SA - Scatter.pdf', bbox_inches='tight') # plt.savefig('JASSS figures/SA - Scatter.png', dpi=300, bbox_inches='tight') plt.show() ``` -------------------------------- ### Track Agent Counts Over Time with repeat_report Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Use `repeat_report` to track the counts of 'wolves' and 'sheep' agents over a specified number of ticks. The results are stored in a dictionary. ```python counts = netlogo.repeat_report(["count wolves", "count sheep"], 200, go="go") ``` -------------------------------- ### Defining a Parallel Simulation Function Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb This function processes a single experiment, setting NetLogo parameters, running the simulation, and returning aggregated results. It handles specific parameter types like 'random-seed' and general global variables. ```python def simulation(experiment): # Set the input parameters for i, name in enumerate(problem["names"]): if name == "random-seed": # The NetLogo random seed requires a different syntax netlogo.command("random-seed {}".format(experiment[i])) else: # Otherwise, assume the input parameters are global variables netlogo.command("set {0} {1}".format(name, experiment[i])) netlogo.command("setup") # Run for 100 ticks and return the number of sheep and wolf agents at each time step counts = netlogo.repeat_report(["count sheep", "count wolves"], 100) results = pd.Series( [np.mean(counts["count sheep"]), np.mean(counts["count wolves"])], index=["Avg. sheep", "Avg. wolves"], ) return results ``` -------------------------------- ### Plot Agent Counts and Phase-Space Plot Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Visualize agent counts over time and create a phase-space plot showing the relationship between wolf and sheep populations. Assumes 'counts' DataFrame is available. ```python fig, (ax1, ax2) = plt.subplots(1, 2) counts.plot(ax=ax1, use_index=True, legend=True) ax1.set_xlabel("Ticks") ax1.set_ylabel("Counts") ax2.plot(counts["count wolves"], counts["count sheep"]) ax2.set_xlabel("Wolves") ax2.set_ylabel("Sheep") for ax in [ax1, ax2]: ax.set_aspect(1 / ax.get_data_ratio()) fig.set_size_inches(12, 5) plt.tight_layout() plt.show() ``` -------------------------------- ### Import Libraries for PyNetLogo Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Imports necessary Python libraries for data manipulation and visualization, along with the PyNetLogo library. ```python %matplotlib inline import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import pyNetLogo ``` -------------------------------- ### repeat_report(netlogo_reporter: str, reps: int, go: str = 'go', include_t0: bool = True) Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Return values from a NetLogo reporter over a number of ticks. ```APIDOC #### repeat_report(netlogo_reporter: str, reps: int, go: str = 'go', include_t0: bool = True) Return values from a NetLogo reporter over a number of ticks. > Can be used with multiple reporters by passing a list of strings. > The values of the returned DataFrame are formatted following the > data type returned by the reporters (numerical or string data, > with single or multiple values). If the reporter returns multiple > values, the results are converted to a numpy array. > netlogo_reporter > : Valid NetLogo reporter(s) > reps > : Number of NetLogo ticks for which to return values > go > : NetLogo command for running the model (‘go’ by default) > include_t0 > : include the value of the reporter at t0, prior to running the > go command dict : > key is the reporter, and the value is a list order by ticks
NetLogoException : If reporters are not in a valid format, or if a LogoException or CompilerException is raised by NetLogo
This method relies on files to send results from netlogo back to Python. This is slow and can break when used at scale. For such use cases, you are better of using a model specific way of interfacing. For example, have a go routine which accumulates the relevant reporters into lists. First run the model for the required time steps using command, and next retrieve the lists through report. ``` -------------------------------- ### Visualize Parameter-Output Correlations with Scatter Plots Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Generates bivariate scatter plots to visualize the relationship between each input parameter and the model output (average sheep count). Calculates and annotates the Pearson correlation coefficient for each parameter. Requires `matplotlib`, `scipy`, and `seaborn`. ```python %matplotlib import scipy nrow = 2 ncol = 3 fig, ax = plt.subplots(nrow, ncol, sharey=True) sns.set_context("talk") y = results["Avg. sheep"] for i, a in enumerate(ax.flatten()): x = param_values[:, i] sns.regplot( x, y, ax=a, ci=None, color="k", scatter_kws={"alpha": 0.2, "s": 4, "color": "gray"}, ) pearson = scipy.stats.pearsonr(x, y) a.annotate( "r: {:6.3f}".format(pearson[0]), xy=(0.15, 0.85), xycoords="axes fraction", fontsize=13, ) if divmod(i, ncol)[1] > 0: a.get_yaxis().set_visible(False) a.set_xlabel(problem["names"][i]) a.set_ylim([0, 1.1 * np.max(y)]) fig.set_size_inches(9, 9, forward=True) fig.subplots_adjust(wspace=0.2, hspace=0.3) ``` -------------------------------- ### Pushing Current Working Directory to Engines Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Pushes the current working directory of the notebook to a 'cwd' variable on all engines. This is useful for ensuring engines can access local files, such as the NetLogo model. ```python import os # Push the current working directory of the notebook to a "cwd" variable on the engines that can be accessed later direct_view.push(dict(cwd=os.getcwd())) ``` -------------------------------- ### Define and Execute NetLogo Procedure Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Defines a NetLogo procedure named 'test' that reports the value 10. This snippet shows how to embed NetLogo code within a Python string. ```python command = """ to-report test report 10; end """ # setup; # let history []; # repeat 10 [ # go; # set history lput count sheep history ``` -------------------------------- ### Plot Circles for SALib Visualization Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_sequential.ipynb Helper function to plot circles representing sensitivity indices on a radial plot. It scales circle radii based on normalized index values. ```python def plot_circles(ax, locs, names, max_s, stats, smax, smin, fc, ec, lw, zorder): s = np.asarray([stats[name] for name in names]) s = 0.01 + max_s * np.sqrt(normalize(s, smin, smax)) fill = True for loc, name, si in zip(locs, names, s): if fc == "w": fill = False else: ec = "none" x = np.cos(loc) y = np.sin(loc) circle = plt.Circle( (x, y), radius=si, ec=ec, fc=fc, transform=ax.transData._b, zorder=zorder, lw=lw, fill=True, ) ax.add_artist(circle) ``` -------------------------------- ### Plotting Sobol Indices with SALib Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Visualizes Sobol' indices using a radial plot. Filters variables based on a specified criterion and threshold. Requires SALib, pandas, and matplotlib. ```python from SALib.plotting.bar import plot as plot_bar from SALib.plotting.sobol import plot as plot_sobol from SALib.test_functions import Sobol_G from SALib import ProblemSpec # Define the problem sp = ProblemSpec({'names': ['x1', 'x2', 'x3'], 'num_vars': 3, 'bounds': [[0, 1]] * 3}) # Run Sobol analysis Si = sp.sobol.analyze(Sobol_G, print_to_console=False) # Plotting the results plot_sobol(Si) plt.show() plot_bar(Si) plt.show() ``` -------------------------------- ### Report Agent Properties in Python Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Retrieve and sort agent properties like coordinates and energy from NetLogo agents into Python variables. Ensures consistent ordering for plotting. ```python x = netlogo.report("map [s -> [xcor] of s] sort sheep") y = netlogo.report("map [s -> [ycor] of s] sort sheep") energy_sheep = netlogo.report("map [s -> [energy] of s] sort sheep") energy_wolves = netlogo.report("[energy] of wolves") # NetLogo returns these in random order ``` -------------------------------- ### Visualize Agent Data with Matplotlib and Seaborn Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Visualize agent data using Matplotlib and Seaborn. Creates a scatter plot of agent positions colored by energy and histograms of energy distribution for sheep and wolves. ```python from mpl_toolkits.axes_grid1 import make_axes_locatable fig, ax = plt.subplots(1, 2) sc = ax[0].scatter(x, y, s=50, c=energy_sheep, cmap=plt.cm.coolwarm) ax[0].set_xlabel("xcor") ax[0].set_ylabel("ycor") ax[0].set_aspect("equal") divider = make_axes_locatable(ax[0]) cax = divider.append_axes("right", size="5%", pad=0.1) cbar = plt.colorbar(sc, cax=cax, orientation="vertical") cbar.set_label("Energy of sheep") sns.histplot(energy_sheep, kde=False, bins=10, ax=ax[1], label="Sheep") sns.histplot(energy_wolves, kde=False, bins=10, ax=ax[1], label="Wolves") ax[1].set_xlabel("Energy") ax[1].set_ylabel("Counts") ax[1].legend() fig.set_size_inches(14, 5) plt.show() ``` -------------------------------- ### report_while Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pynetlogo.md Returns values from a NetLogo reporter while a specified condition remains true. Execution can be limited by a maximum duration. ```APIDOC ## report_while(netlogo_reporter: str, condition: str, command: str = 'go', max_seconds: int = 10) ### Description Return values from a NetLogo reporter while a condition is true in the NetLogo model. ### Parameters #### Path Parameters - **netlogo_reporter** (str) - Required - Valid NetLogo reporter - **condition** (str) - Required - Valid boolean NetLogo reporter - **command** (str) - Optional - NetLogo command used to execute the model (defaults to 'go') - **max_seconds** (int) - Optional - Time limit used to break execution (defaults to 10 seconds) ### Raises - **NetLogoException**: If a LogoException or CompilerException is raised by NetLogo ``` -------------------------------- ### Simulation Function for Parallel Execution Source: https://github.com/quaquel/pynetlogo/blob/master/examples/SALib_ipyparallel.ipynb Defines a function to run a single simulation experiment. It sets NetLogo parameters, runs the model for a specified duration, and returns aggregated results as a pandas Series. ```python def simulation(experiment): # Set the input parameters for i, name in enumerate(problem["names"]): if name == "random-seed": # The NetLogo random seed requires a different syntax netlogo.command("random-seed {}".format(experiment[i])) else: # Otherwise, assume the input parameters are global variables netlogo.command("set {0} {1}".format(name, experiment[i])) netlogo.command("setup") # Run for 100 ticks and return the number of sheep and wolf agents at each time step counts = netlogo.repeat_report(["count sheep", "count wolves"], 100) results = pd.Series( [counts["count sheep"].values.mean(), counts["count wolves"].values.mean()], index=["Avg. sheep", "Avg. wolves"], ) return results ``` -------------------------------- ### Visualize Updated Patch Data Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Retrieve and visualize the updated patch data after using `patch_set` to confirm the changes. This uses `patch_report` and `sns.heatmap`. ```python countdown_update_df = netlogo.patch_report("countdown") fig, ax = plt.subplots(1) patches = sns.heatmap( countdown_update_df, xticklabels=5, yticklabels=5, cbar_kws={\"label\": \"countdown\"}, ax=ax, ) ax.set_xlabel("pxcor") ax.set_ylabel("pycor") ``` -------------------------------- ### Report Value from NetLogo Source: https://github.com/quaquel/pynetlogo/blob/master/examples/Untitled.ipynb Reports a value from the NetLogo model. This will raise a NetLogoException if the reported variable or primitive is not defined. ```python netlogo.report("test") ``` -------------------------------- ### Report List Data with repeat_report Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Use `repeat_report` to collect list data, such as agent energy, over a number of ticks. Results for list reporters are converted to NumPy arrays. The last element of the energy array is plotted. ```python results = netlogo.repeat_report( [ "[energy] of wolves", "[energy] of sheep", "[sheep_str] of sheep", "count sheep", "glob_str", ], 5, ) fig, ax = plt.subplots(1) sns.histplot(results["[energy] of wolves"][-1], kde=False, bins=20, ax=ax) ax.set_xlabel("Energy") ax.set_ylabel("Counts") fig.set_size_inches(4, 4) plt.show() ``` -------------------------------- ### Convert Sobol Indices to DataFrame Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/SALib_ipyparallel.ipynb Filters and converts the Sobol indices dictionary returned by SALib into a pandas DataFrame for easier manipulation and visualization. Requires pandas. ```python Si_filter = {k: Si[k] for k in ["ST", "ST_conf", "S1", "S1_conf"]} Si_df = pd.DataFrame(Si_filter, index=problem["names"]) ``` -------------------------------- ### Display Sensitivity Analysis DataFrame Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/pyNetLogo demo - SALib sequential.ipynb Displays the pandas DataFrame containing the calculated Sobol indices (S1 and ST) and their confidence intervals. ```python Si_df ``` -------------------------------- ### Inspect repeat_report Keys Source: https://github.com/quaquel/pynetlogo/blob/master/docs/source/_docs/introduction.ipynb Display the keys of the dictionary returned by `repeat_report`, which correspond to the reporters used in the call. ```python list(results.keys()) ```