Tutorials

Step-by-step guides for learning joshpy.

Getting Started

Single Run & Iteration

The essential workflow: run a simulation, tweak parameters, compare results.

  • Use raw .jshc config files with auto-parsed parameters
  • Label runs with .with_label() for easy comparison
  • Compare with plot_comparison(group_by="label")
  • Track experiments across sessions with ProjectCatalog

Best for: Day-to-day research iteration. Start here.

SweepManager Workflow

Systematic parameter sweeps using SweepManager:

  • Builder pattern for configuration
  • Automatic registry management and result loading
  • Cartesian product of parameter combinations

Best for: When you know what to sweep and want to cover the space.

Analysis & Visualization

Explore and visualize simulation results:

  • Data discovery with registry.get_data_summary()
  • Diagnostic plots with SimulationDiagnostics
  • Custom queries with DiagnosticQueries
  • Direct SQL access to DuckDB
  • R/ggplot2 integration for publication-quality figures

Best for: Understanding the analysis layer (works with any registry).

External Data

Preprocessing External Data

Convert geospatial data to Josh’s optimized .jshd format:

  • Preprocess NetCDF, GeoTIFF, and CSV files with cli.preprocess()
  • Verify data with load_jshd()
  • Spatial alignment to simulation grids

Best for: Preparing climate, land cover, or other external data.

Sweeping Over External Data

Run simulations with different input data files:

  • FileSweepParameter for data file sweeps
  • CompoundSweepParameter for co-varying file groups
  • Compare scenarios (e.g., SSP126 vs SSP245)

Best for: Comparing climate scenarios, sensitivity to input data.

GridSpec Variant Sweeps

Automate file sweeps using GridSpec variant declarations:

  • Declare variant axes in grid.yaml with template_path placeholders
  • variant_sweep() generates CompoundSweepParameter automatically
  • Combine with ConfigSweepParameter for cartesian parameter x scenario sweeps
  • Full end-to-end example with .josh.j2, .jshc.j2, and GridSpec

Best for: Structured projects where data files follow a naming convention by scenario.

Timestep Interventions

Use single-time external data for initialization and discrete events:

  • Initialize populations from spatial inventory data
  • Apply disturbance events at specific timesteps
  • Conditional logic with meta.stepCount

Best for: Initial conditions from COGs, discrete disturbance events.

Project Structure

Project Organization

Structure multi-grid, multi-model projects:

  • Recommended directory layout
  • GridSpec for grid geometry and data manifests
  • .josh.j2 model templates to avoid file duplication

Best for: Real projects with multiple grids or model variants.

Complete Example

Full lifecycle with all three template types working together:

  • Ad-hoc iteration with GridSpec, .josh.j2, and .jshc.j2
  • Promote to a cartesian parameter x variant sweep
  • Track everything with ProjectCatalog

Best for: Seeing all joshpy components in one end-to-end workflow.

Multi-Session Sweeps

Track parameter sweeps across sessions with ProjectCatalog:

  • One registry per sweep, catalog indexes them all
  • Deduplication: check if a sweep was already run
  • Recall past sweep registries for analysis

Best for: Projects with multiple systematic sweeps to keep organized.

Inspecting Runs from the Registry

View, export, and diff stored configs and josh sources:

  • registry.export_config() and registry.export_josh() for file export
  • registry.compare_configs() and registry.compare_josh() for IDE diffing
  • python -m joshpy.inspect CLI for terminal use
  • Smart file resolution (real file when unchanged, snapshot when drifted)

Best for: Understanding what changed between runs, debugging failures.

Debugging & Profiling

Bottling Runs for Reproducibility

Create self-contained archives for bug reports, archival, and sharing:

  • manager.run(bottle="first_failure") to capture failures automatically
  • registry.bottle("baseline") to package a past run after the fact
  • Archive includes run.sh – reproduce with just Java and the JAR

Best for: Bug reports, sharing reproducible examples, long-term archival.

Debug Output Inspection

Trace agent behavior with structured debug log analysis:

  • Parse and filter debug output programmatically
  • python -m joshpy.debug CLI with colored terminal output
  • Trace individual entities across timesteps

Best for: Understanding why agents behave a certain way.

Finding Bottlenecks

Two profiling approaches for different needs:

  • Josh profiling (enable_profiler=True): measure attribute evaluation time with .evalDuration – best for optimizing model logic
  • JFR profiling (JfrConfig): JVM-level CPU/GC/memory analysis – best for the Josh team diagnosing runtime issues

Best for: Understanding where time is spent in your simulation.

Advanced

Adaptive Parameter Optimization

Use Optuna’s Bayesian optimization for intelligent parameter search:

  • OptunaStrategy for adaptive sampling
  • Custom objective functions
  • Efficient exploration of large parameter spaces

Best for: Finding optimal parameters without exhaustive grid search.

Low-Level Components

Use joshpy’s individual components directly:

  • JobExpander for manual job expansion
  • RunRegistry for direct registry management
  • run_sweep() for custom execution loops

Best for: Understanding internals or building custom workflows.

Switching Josh Versions

Switch between stable, development, and custom Josh builds.

Best for: Testing new Josh features or pinning versions.

Running on Josh Cloud

Distribute simulations across Josh Cloud for parallel execution.

Best for: Large sweeps where local execution would be too slow.

Prerequisites

All tutorials assume:

  1. joshpy is installed with all dependencies: pip install joshpy[full]
  2. Josh JAR is available (auto-downloaded if needed)
  3. Java 17+ is installed