Skip to main content

A framework for agent-based modeling of dynamic spatial processes.

Project description

NexusSim

NexusSim is a flexible and powerful Python framework for agent-based modeling of dynamic spatial processes. Designed for modularity and scientific reproducibility, it allows users to simulate complex emergent phenomena on customizable landscapes - from disease epidemics and invasive species to wildlife spread and information diffusion.

The framework is built on a decoupled, file-based architecture: the simulation engine produces a series of GeoTIFF raster files, which are then consumed by a comprehensive analysis toolbox to generate plots, animations, and statistics.

Key Features

  • Agent-Centric Simulation: Models complex behaviors by focusing on individual agent states and interactions (nexussim.core).
  • Raster-Based I/O: Works seamlessley with standard geospatial data formats for defining landscapes and initial conditions.
  • Comprehensive Analysis Suite: A rich set of tools (nexussim.analysis) to generate epidemic curves, animations, persistence "hotspot" maps, and calculate the rate of spread.
  • Reproducibility First: The file-based output creates a permanent, reproducible record of every simulation run.
  • Scalable: By not holding the entire simulation history in memory, NexusSim can hanlde longer and larger simulations.

Installation

NexusSim is available on PyPI. Install it using pip:

pip install nexussim

To install the latest development version directly from GitHub:

pip install git+https://github.com/mrmarcelino/nexussim.git

Quickstart: From Simulation to Analysis

This example demonstrates the complete NexusSim workflow. It will:

  1. Create dummy input rasters for a landscape and initial infections.
  2. Run a 50-step simulation, saving the output to a results/ directory.
  3. Use the analysis module to generate an epidemic curve plot and an animated GIF from the results.
import os
import shutil
import numpy as np
import rasterio
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

# nexussim/
# |- __init__.py
# |- core.py
# |- analysis.py
from nexussim.core import DiseaseModel
import nexussim.analysis as nxs_analysis
# Helper function to create dummy input data
def create_dummy_raster(path, width, height, data, crs='EPSG:3857'):
  """
  Creates a simple GeoTIFF file for demonstration purposes.
  """
  profile ={
      'driver': 'GTiff',
      'dtype': 'float32',
      'width': width,
      'height': height,
      'count': 1,
      'crs': crs,
      'transform': rasterio.transform.from_origin(0, height, 1, 1),
      'nodata': -9999
  }
  with rasterio.open(path, 'w', **profile) as dst:
    dst.write(data.astype(profile['dtype']), 1)
# 1. Setup Environment and Input Data
print("--- Setting up simulation environment ---")
# Create directories for inputs, simulation outputs, and analysis outputs
os.makedirs('inputs', exist_ok=True)
os.makedirs('sim_results', exist_ok=True)
os.makedirs('analysis_outputs', exist_ok=True)

# Define file paths
cost_path = 'inputs/cost.tif'
initial_infection_path = 'inputs/initial_infection.tif'
width, height = 100, 100

# Create a uniform cost surface (all areas are equally passable)
cost_data = np.ones((height, width))
create_dummy_raster(cost_path, width, height, cost_data)

# Create an initial infection raster with a small cluster of infected cells
initial_infection_data = np.zeros((height, width))
initial_infection_data[45:55, 45:55] = 1
create_dummy_raster(initial_infection_path, width, height, initial_infection_data)
print(" > Dummy input rasters created.")

# 2. Run the Simulation
print("\n--- Running the NexusSim simulation ---")
model_params = {
    'cost_threshold': 1.0, # Agents can move anywhere
    'spread_probability': 0.6,
    'infection_duration': 5,
    'recovery_time_min': 10,
    'recovery_time_max': 20
}

# Initialize the model
model = DiseaseModel(cost_path, initial_infection_path, model_params)

# Run the simulation, which saves raster files to 'sim_results/'
model.run_simulation(time_steps=50, output_dir='sim_results')

# 3. Analyze the Results
print("\n--- Analyzing simulation results ---")
# First, get the list of generated files
tif_files = nxs_analysis.get_simulation_files('sim_results')

if tif_files:
  # Generate and save an epidemic curve plot
  curve_plot_path = 'analysis_outputs/epidemic_curve.png'
  nxs_analysis.generate_epidemic_curve(tif_files, curve_plot_path)

  # Create and save an animation
  animation_path = 'analysis_outputs/animation.gif'
  nxs_analysis.create_animation(tif_files, animation_path, duration=0.1)
  print(" > Analysis complete. Outputs are in 'analysis_outputs\'.")

  # 4. Display one of the generated plots
  print("\n--- Displaying generated epidemic curve ---")
  img = mpimg.imread(curve_plot_path)
  plt.figure(figsize=(10, 6))
  plt.imshow(img)
  plt.axis('off') # Hide axes as the image already has them
  plt.show()
else:
  print("Analysis skipped: No simulation files were found.")

The NexusSim Workflow

NexusSim is intentionally designed to separate the simulation from the analysis. This provides several key advantages for scientific modeling:

  1. Reproducibility: The output rasters serve as a permanent, shareable record of the simulation.
  2. Flexibility: You can run multiple analyses on a single simulation output without having to re-run the entire model.
  3. Extensibility: It's easy to write your own custom analysis functions that operate on the standardized GeoTIFF outputs. The standard workflow looks like this: [Input Rasters]nexussim.core.DiseaseModel[Output Rasters]nexussim.analysis[Plots, GIFs, & Stats]

Core Components

  • nexussim.core: Contains the Agent and DiseaseModel classes. This is the heart of the simulation engine responsible for running the model and saving the state at each time step.
  • nexussim.analysis: A toolbox of standalone functions that take a list of raster file paths as input and produce high-level outputs like plots, statistics, or animations.

Contributing

Contributions are welcome! If you have ideas for new features, analysis tools, or improvements, please open an issue or submit a pull request.

License

This project is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0) - see the LICENSE.md file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nexussim-0.1.1.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nexussim-0.1.1-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file nexussim-0.1.1.tar.gz.

File metadata

  • Download URL: nexussim-0.1.1.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for nexussim-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ad8effd561ef704982dbbfe69947b716ffa4316f2ce6599d9aff8871a23ac75f
MD5 469c9b97326de771ccc63bca16847bb6
BLAKE2b-256 0b322ec4cc8ebb10bed5ae78d178a5d14a2e3940f82eaa8e7783725f35275ff0

See more details on using hashes here.

File details

Details for the file nexussim-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: nexussim-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for nexussim-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d29f34a9d50126a9120d0beae7d73c343b48b43fc6be9da8dcefa7fb18e2aecb
MD5 11b12a4612d399c18eaa25894f590ebb
BLAKE2b-256 e1a5fc622b6c187a568937026f1a741524beb7bb11d347c4644f2187195b8324

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page