Skip to contents

Prompts

I want to develop an app in this repo that begins with
a simulation at some stage, say

mysim <- init.simulation()
mysim <- future.events(mysim, nstep=100)

I want to visualize the position of each organism on the hexagonal substrate of the `triangleApp()` app (with hexagonal grid overlay instead of centroid points) using
symbols as in `substrateApp()`. Place organisms on hexagons
based on their triangular coordinates rather than the horizontal/vertical system used in `substrateApp()`.
I want to be able to step through the simulation, either
one step at a time or multiple steps.

Architectural Rationale & Overview

The hexmoveApp application visualizes host and parasite spatial positions mapped directly onto a unified hexagonal substrate network topology (create_substrate).

Instead of rendering substrate components (fr1..fr4, tw1..tw2, lftop, lfbot) in isolated rectangular panel facets (as done in the original substrateApp()), hexmoveApp places every organism on a continuous hexagonal substrate plane based on its native tridiagonal coordinates (a,b,c)(a, b, c) and its active substrate patch (sub.stage).

Organism coordinates are dynamically rescaled per substrate component so that all individuals are visualized strictly within the boundaries of their respective substrate surface patches (fr1, fr2, lftop, twig, etc.).


Substrate Resolution & Rescaling Coordinate Mapping

1. Substrate Component Resolution

Each organism in an ewing simulation tracks its substrate position in individual["sub.stage"]. This integer index maps to specific plant substrate elements defined in getOrgInteract(community, substrate, species): - fr1, fr2, fr3, fr4: Fruit component facets - twig / tw1, tw2: Twig component facets - lftop, lfbot: Leaf top and bottom surface facets

substrate_topology defines topological offsets 𝐨=(oa,ob,oc)\mathbf{o} = (o_a, o_b, o_c) and component orientations (dir = "up" or "down") for each substrate element. Substrate component names like twig are mapped to tw1 to ensure every individual is placed precisely on its active substrate patch.

2. Per-Substrate Unit Triangle Rescaling

Simulation coordinates generated by init.population(width = 100) or rtri() span up to 100 units. To map organisms accurately within substrate surface triangles of size WsubW_{sub} (which may vary per substrate in future configurations):

  1. Local Coordinate Normalization: For the subset of organisms on substrate SS: ui=pos.aiβˆ’min⁑(pos.a)max⁑(pos.a)βˆ’min⁑(pos.a),vi=pos.biβˆ’min⁑(pos.b)max⁑(pos.b)βˆ’min⁑(pos.b)u_i = \frac{pos.a_i - \min(pos.a)}{\max(pos.a) - \min(pos.a)}, \quad v_i = \frac{pos.b_i - \min(pos.b)}{\max(pos.b) - \min(pos.b)} Applying a 15% inner padding buffer (uiβ€²=0.15+0.70ui,viβ€²=0.15+0.70viu'_i = 0.15 + 0.70 u_i, \ v'_i = 0.15 + 0.70 v_i): aiβ€²=uiβ€²β‹…Wsuba'_i = u'_i \cdot W_{sub}biβ€²=viβ€²β‹…(Wsubβˆ’aiβ€²)b'_i = v'_i \cdot (W_{sub} - a'_i)ciβ€²=βˆ’(aiβ€²+biβ€²)c'_i = -(a'_i + b'_i)

  2. Global Tridiagonal Coordinate Transformation:

    • If component orientation is "up": 𝐩𝐨𝐬global=(aiβ€²+oa,biβ€²+ob,ciβ€²+oc)\mathbf{pos}_{global} = (a'_i + o_a, \ b'_i + o_b, \ c'_i + o_c)
    • If component orientation is "down" (inverted triangle): 𝐩𝐨𝐬global=(βˆ’aiβ€²+oa,βˆ’biβ€²+ob,βˆ’ciβ€²+oc)\mathbf{pos}_{global} = (-a'_i + o_a, \ -b'_i + o_b, \ -c'_i + o_c)
  3. Global Cartesian Mapping: Converting 𝐩𝐨𝐬global=(ag,bg,cg)\mathbf{pos}_{global} = (a_g, b_g, c_g) to Euclidean coordinates (xg,yg)(x_g, y_g) via tri2car(): xg=(agβˆ’bg)β‹…22+3x_g = (a_g - b_g) \cdot \frac{2}{2 + \sqrt{3}}yg=βˆ’(ag+bg)β‹…63+23y_g = -(a_g + b_g) \cdot \frac{6}{3 + 2\sqrt{3}}

This guarantees that all organisms on substrate SS are displayed strictly inside that substrate’s surface area.


Multi-Species Display Modes & Filtering

hexmoveApp supports multi-species simulation communities (e.g.Β host and parasite):

  1. Species Filtering: Users can toggle which species to display (Host and/or Parasite) using inline checkboxes in the sidebar (show_species).

  2. Multi-Species View Modes:

    • Overlay (1 Map): Renders all selected species (hosts AND parasites) simultaneously on a single unified hexagonal substrate map. Host stage symbols (0, 1, 2, 3…) and parasite stage symbols (E, L, P, p…) sit together on the same hexagonal grid layout, allowing direct visualization of spatial host-parasite overlaps.
    • Separate (Adjacent Maps): Renders each selected species on its own distinct hexagonal grid map side-by-side (cowplot::plot_grid(ncol = length(species), align = "h")).

Hexagonal Grid Overlay (create_hex_overlay)

A discrete hexagonal grid overlay is generated over the substrate lattice points (sub_obj$points) using create_hex_overlay().

For each lattice center (x0,y0)(x_0, y_0), a 6-sided polygon cell is computed: xk=x0+rcos⁑(Ο€6+kΟ€3),yk=y0+rsin⁑(Ο€6+kΟ€3)for k=0,…,5x_k = x_0 + r \cos\left(\frac{\pi}{6} + \frac{k\pi}{3}\right), \quad y_k = y_0 + r \sin\left(\frac{\pi}{6} + \frac{k\pi}{3}\right) \quad \text{for } k = 0, \dots, 5 where radius r=stepβ‹…d3r = \frac{step \cdot d}{\sqrt{3}} scales with grid spacing step and nearest-neighbor distance d=xmult2+ymult2d = \sqrt{xmult^2 + ymult^2}.


Interactive Simulation Stepping

The interactive controls in substrateInput and substrateServer provide: - Stepping Action Buttons: +1 Step, +10 Steps, +100 Steps, and Reset. Clicking a step button executes future.events(sim, nstep = n) and reactively updates the substrate visualization. - Species Filter & View Modes: Checkboxes for selecting species (host, parasite) and radio buttons for Overlay (1 Map) vs Separate (Adjacent Maps). - Layout Switching: Toggle between "Hex Substrate Overlay" (global hexagonal network) and "Faceted Substrates" (panel view faceted by substrate element fr1..fr4, twig, lftop, lfbot). - Layer Controls: Dynamic checkboxes for Substrate Boundaries (poly), Hex Grid Overlay (hex), Organism Symbols (organisms), Substrate Identifiers (centers), and Side Numbers (labels).


Application Usage

Launch hexmoveApp with an initial simulation object or run default initialization:

library(ewing)

# Initialize simulation and run initial 100 steps
mysim <- init.simulation()
mysim <- future.events(mysim, nstep = 100)

# Launch interactive Shiny app
hexmoveApp(mysim)

The app launcher script is located at inst/scripts/hexmoveApp.R.