Helipad Codex https://helipad.dev Agent-based modeling in Python Sat, 13 Dec 2025 17:14:26 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://helipad.dev/wp-content/uploads/2023/01/cropped-Helipad-32x32.png Helipad Codex https://helipad.dev 32 32 Helipad White Paper Published in the Journal of Open Research Software https://helipad.dev/2025/12/helipad-white-paper-published/ https://helipad.dev/2025/12/helipad-white-paper-published/#respond Sat, 13 Dec 2025 17:14:08 +0000 https://helipad.dev/?p=811 If you use Helipad in your research, the white paper for Helipad has now been published at the Journal of Open Research Software. It can be cited as follows.

Harwick, Cameron (2025). “Helipad: A Framework for Agent-Based Modeling in Python.” Journal of Open Research Software, 13(1).

And the abstract:

Agent-based modeling tools commonly trade off usability against power and vice versa. On the one hand, full development environments like NetLogo feature a shallow learning curve, but have a relatively limited proprietary language. Others written in Python or Matlab, for example, have the advantage of a full-featured language with a robust community of third-party libraries, but are typically more skeletal and require more setup and boilerplate in order to write a model. Helipad is introduced to fill this gap. Helipad is a new agent-based modeling framework for Python with the goal of a shallow learning curve, extensive flexibility, minimal boilerplate, and powerful yet easy to set up visualization, in a full Python environment. We summarize Helipad’s general architecture and capabilities, and briefly preview a variety of models from a variety of disciplines, including multilevel models, matching models, network models, spatial models, and others.

]]>
https://helipad.dev/2025/12/helipad-white-paper-published/feed/ 0
Helipad 1.6 has Scatterplots, Geospatial Models, and New Agents Container https://helipad.dev/2023/06/helipad-1-6/ Thu, 15 Jun 2023 20:25:45 +0000 https://helipad.dev/?p=779 Helipad 1.6 is out now, with a number of new visualization capabilities and model types.

Geospatial Models

Helipad now supports spatial models with arbitrary polygonal patches, using geometry='geo' when initializing a spatial model. Geospatial models are common in a variety of fields where actual geographic borders matter.

The model.patches container will be instantiated as the new PatchesGeo class, which stores patches as a list and allows new patches to be added one by one. Patch shapes can be imported from a GeoJSON or other GIS format using GeoPandas. As with the rectangular and polar geometries, patches are connected by a 'spatial' network to their bordering neighbors and (optionally) to patches they are connected to only by a corner. Agents can optionally be confined to patches, or wander into non-patch areas, with the offmap argument.

Geospatial models require Shapely, which can be installed with pip install shapely.

Scatterplot Visualizer

The visualizer formerly known as NetworkPlot – which was merged with the spatial visualizer in Helipad 1.3 – has been renamed to AgentsPlot to reflect its variety of layouts, all of which plot individual agents in one way or another.

In addition to spatial layout and a variety of network layouts, AgentsPlot now also features a scatterplot layout. A scatterplot can be initialized by passing a scatter=('prop1','prop2') argument to Charts.addPlot(), which will plot agent.prop1 and agent.prop2 on a scatterplot with an optional regression line. The usual network and spatial layouts can also be rotated through as usual by pressing L, if applicable (though network layouts will now be skipped if there is no network specified). Agent holdings of a good can also be plotted by passing 'good:goodname' as the property name.

New Agents Container

A number of model-level functions have been moved to model.agents, which now not only stores agents by primitive as a dict of lists, but also provides an interface to interact with and control agents. This comes with a number of improvements:

  • More logical function organization. A number of top-level methods and properties pertaining to agents – for example model.order or model.createNetwork() – have been moved to the Agents container: model.agents.order and model.agents.createNetwork(). Old code will continue to work per the deprecation policy, but aliases to the original functions will be removed in Helipad 1.8.
  • Merged Primitives container. The Primitive data object now resides in model.agents and contains the agents of that primitive as a subclass of list. The dedicated model.primitives container is now deprecated, and primitives can be added with model.agents.addPrimitive(). Because Agents subclasses dict and Primitive subclasses list, the Agents container stores agents in the exact same way as a dict of lists organized by primitive.
  • More flexible agent access. A list of agents of a primitive can be gotten as usual by model.agents['primitive'], but agents can also be retrieved individually by ID with a numeric index, e.g. model.agents[123], replacing the model.agent() function. A list of all agents can be retrieved with model.agents.all. Agents can be retrieved by breed with a double index, e.g. model.agents['primitive']['breedname'].

Other Improvements

  • Patches can now die. This removes the patch from the map and optionally prevents agents from moving to the corresponding area with the offmap argument. Since they are a fixed primitive, patches can also be revived.
  • Patches have center, area, and vertices properties.
  • Helipad modules and methods now have docstrings with links to full documentation, which will be helpful for users working with IDEs like Pylance or Visual Studio Code.
  • New Edges container. Network edges can be added and retrieved with agent.edges.add(), agent.edges['networkname'], agent.edges.inbound(), agent.edges.all, etc.

API Changes in Version 1.6

  • ⚠ addBreedMoved from Model.addBreed().
  • ⚠ MPLVisualizationRenamed the keys property to keyListeners and the update() method to refresh to avoid collisions with dict methods.
    sendEvent() is no longer a bound method due to a Matplotlib bug.
    Deprecated the plots property. Plots can now be retrieved directly from the visualization object, like model.visual['plotName'].
  • ⚠ refreshRenamed from update() to avoid a collision with dict methods.
  • ⚠ paramSimplified the parameter identification tuple from (paramName, itemType, itemName, Primitive) to (paramName, itemName).
  • ⚠ baseAgentMoved Agent.alledges to Agent.edges.all.
  • ⚠ addSimplified the parameter identification tuple from (paramName, itemType, itemName, Primitive) to (paramName, itemName).
  • ⚠ paramSweepSimplified the parameter identification tuple from (paramName, itemType, itemName, Primitive) to (paramName, itemName).
  • ⚠ createNetworkMoved from Model.createNetwork().
  • ⚠ networkMoved from Model.network().
  • ⚠ AgentsMerged the Primitives container object into the Agents dict and took on a number of agent-relevant properties and methods from the main model object.
    Allow retrieval of individual agents with an int dict key.
  • ⚠ addPrimitiveMoved from Primitives.add() with the merging of the Primitives and Agents objects.
  • ⚠ removePrimitiveMoved from Primitives.remove() with the merging of the Primitives and Agents objects.
  • ⚠ HelipadMerged model.primitives into model.agents.
    Deprecated model.allagents in favor of model.agents.all.
    Moved model.addBreed() to Agents.addBreed().
    Moved model.order to Agents.order.
    Moved network methods and properties model.network(), model.createNetwork(), and model.allEdges to the Agents object.
    Deprecated model.agent(id) in favor of model.agents[id] and model.agent(breed, prim) in favor of model.agents[prim][breed].
  • ⚠ AgentsPlotRenamed from NetworkPlot to AgentsPlot in order to encompass the variety of layouts now supported.
    Now supports scatterplot layouts and geospatial models.
    Renamed the kind argument and property to network.
  • showIntroduced.
  • hideIntroduced.
  • showIntroduced.
  • renderParamIntroduced.
  • hideIntroduced.
  • configAdded the mapBg and regression parameters.
  • rotateLayoutSkips the NetworkX layouts if no network exists.
  • PatchesGeoIntroduced.
  • neighborsChanged from a per-patch function to establishing patch edges all at once.
  • EdgesIntroduced.
  • MultiDictIntroduced.
  • PrimitiveNow stores Agent objects as a list.
    Agents can be retrieved by breed using Primitive[breed].
  • initializeMoved from Model.nUpdater().
  • basePatchesChanged to an abstract base class.
    Added the offmap property.
  • atIntroduced.
  • PatchIntroduced the center, area, and vertices properties.
    Patches can die now.
  • spatialAdded the offmap argument.
]]>
Helipad 1.5 Supports Polar Spatial Models https://helipad.dev/2023/01/helipad-1-5/ https://helipad.dev/2023/01/helipad-1-5/#respond Sat, 14 Jan 2023 21:52:22 +0000 https://helipad.dev/?p=710

Helipad 1.5 comes with the big improvement of supporting multiple coordinate systems with model.patches now defining a coordinate system with subclasses of basePatches. Helipad comes bundled with a rectangular and (now) a polar coordinate system, along with visualizers for each. Spatial models are initialized by default with rectangular geometry, but can be changed to polar by passing geometry='polar' to model.spatial(). Pictured right is the standard sheep and grass population model, but on an 8×16 polar rather than a rectangular grid.

In addition, Helipad 1.5 comes with numerous other improvements to spatial models and more.

Spatial improvements

  • For rectangular geometries, wrapping can now be toggled on a per-axis basis (allowing cylindrical geometries in addition to toroidal) by passing wrap=(True, False) or wrap=(False, True) to model.spatial().
  • agent.orientTo() and agent.distanceFrom() now take the shorter path if they can cross a wrap boundary.
  • A new setting allows angles to be expressed and set using either degrees or radians. This can be set globally with the static property baseAgent.angleUnit, which can be set to 'deg' or 'rad'. (This does not modify individual agent objects: orientation is stored internally in radians either way, but agent.orientation will report the angle in the units specified by the setting.)
  • agent.orientation and agent.rotate are now available and can be set before a spatial model is initialized. Patches return an orientation of None rather than raising a RuntimeError (though a RuntimeError will still be raised when trying to set a patch orientation).
  • The diag argument of model.spatial() has been renamed to corners, as this generalizes better to non-rectangular geometries. The diag argument has been deprecated, but aliases corners.
  • Rows of patches can be retrieved with model.patches[None, rownum]. Columns and individual patches continue to be accessed as before using one or two arguments respectively.
  • The 'x', 'y', and 'wrap' parameters are deprecated. These settings are now stored in the dim and wrap properties of model.patches. They are thus no longer settable in the control panel by default, though this behavior can be restored with an additional two lines of code.

Console improvements

  • Helipad objects now have more informative __repr__ methods. For example, calling a patch will now display <Patch at 5,5> rather than <helipad.agent.Patch object at 0x120c9e490>.
  • model.timer will now update the same line when launched from an interactive console, rather than accumulating lines.

Misc improvements

  • Helipad now remembers the size and position of the visualization window for new model runs.
  • Helipad now uses pyproject.toml for packaging rather than the legacy setup.py.
  • Fixed a bug where selected=False would sometimes be ignored when adding a plot to the Charts visualizer.
  • Localization now no longer installs _ into the global scope.

API Changes in Version 1.5

  • ⚠ spatialRenamed the diag argument to corners in order to accommodate non-square grids.
    Allowed Agent.orientation to be expressed in either degrees or radians depending on the value of Agent.angle.
    The wrap argument can now take (True, False) or (False, True) values to set horizontal and vertical wrapping independently.
    Added the geometry argument.
  • baseAgentAdded the angleUnit static property.
  • checkEntryRenamed the type argument to datatype to avoid name conflict.
  • basePatchesIntroduced.
  • PatchesRectIntroduced.
  • PatchesPolarIntroduced.
]]>
https://helipad.dev/2023/01/helipad-1-5/feed/ 0
Helipad 1.4 brings Interface Improvements and New Container API https://helipad.dev/2022/07/helipad-1-4/ https://helipad.dev/2022/07/helipad-1-4/#respond Thu, 28 Jul 2022 03:07:34 +0000 https://helipad.dev/?p=660 Helipad 1.4 has arrived, with the most important feature being a more consistent API for container classes. A new dict-like funcStore class now stores parameters, goods, primitives, shocks, hooks, and events. This provides a simple and standardized interface for adding, removing, and clearing all of the above.

Instead of … now use …

In addition, standardization makes it possible to remove shocks, parameters, goods, and breeds, where this was not possible before.

Helipad 1.4 also has a number of smaller features and bugfixes:

  • Installable from Conda. Helipad can now be installed with Conda instead of Pip, using conda install -c charwick helipad
  • Localization. Helipad can now be translated into and launched with other languages. While currently only an English localization exists, translators can contribute using the string template.
  • Parameter groups. Global parameters can be grouped into expandable frames.
    A parameter group in a Jupyter notebook
    A parameter group in the Tkinter frontend
  • Toggle-all buttons. Checkgrid parameters now have a button in the header for toggling on and off all the options at once.
    Toggle-all button in a Jupyter notebook
    Toggle-all button in the Tkinter frontend
  • model.cutStep(). Allows agents to be skipped during a model step, e.g. when testing if any agent will succeed in a period, there is no need to step through further agents that period once one does.
  • Agent overdraft control. Helipad now provides options for what to do when .trade() or .pay() has the agent giving up more than he has. Agents can either continue with existing balances (as was the default before), allow negative balances, or abort the trade, and the model can either continue, warn, or raise an error.
    • Shortage reporters are no longer kept track of in core, as shortages have no clear meaning for some overdraft settings. Models keeping track of shortages can do so by observing discrepancies between the input and output values of .pay().
  • Windows 11 compatibility.
  • New saveCSV hook. CSV output can now be modified before saving.
  • New icon. Helipad now displays its own icon in the dock/taskbar when launching using the Tkinter frontend, rather than the default Python launcher’s icon.
    The Helipad icon in the dock
    Helipad in the Windows taskbar
  • More reliable tooltips. Parameters registered with the desc argument now display tooltips in the Tkinter frontend even if PMW is not installed. Tooltips continue to display as normal in Jupyter notebooks.
    Tooltips
  • Position and resize visualization windows. MPLVisualizations (i.e. all the built-in visualizations) now have dim and pos properties that can be set before launch.
  • More useful callback values. Checkgrid parameters now pass a (name, val) tuple to their callback function, indicating which checkbox was turned on or off, rather than just the value of that checkbox.
  • Better post-analysis. Models can now be run from the control panel with no visualizations selected if stopafter is set and a terminate hook is registered. Previously, doing so required stopafter to be set and CSV export to be enabled.
  • Namespace cleanup. from helipad import * no longer also imports Numpy into the namespace.
  • Cleaner spatial dimension-setting. The spatial() function takes a single dim=(x,y) tuple or int, replacing the three x=x, y=y, square=bool arguments.
  • Bug fixes.
    • Fixed a bug where parameter sweeps wouldn’t run if a visualizer was registered, even if no plots were selected
    • Fixed a bug where the CpanelPostInit hook wouldn’t run when launching a model with the debug console running.
    • Helipad 1.4.1 has updated for compatibility with breaking changes in Ipywidgets 8.0 and is not compatible with Ipywidgets 7 or earlier. If you need compatibility with Ipywidgets 7, you can use pip install helipad==1.4 to install Helipad 1.4.0. The Tkinter frontend is not affected.

API Changes in Version 1.4

  • ⚠ HelipadThe goodParams, moneyGood, and nonMoneyGoods properties have been deprecated. Use params.perGood, goods.money, and goods.nonmonetary instead.
    Deprecated the addParameter, addGoodParameter, addBreedParameter, addEvent, removeEvent, clearEvents, addHook, removeHook, clearHooks, addPrimitive, removePrimitive, and addGood methods. These have been replaced by standard container interfaces Params, Events, Hooks, Primitives, and Goods.
    Added the locale argument.
  • ⚠ addMoved from model.addGood().
  • ⚠ removeMoved from model.removeHook.
  • ⚠ addMoved from model.addHook().
  • ⚠ PrimitiveRemoved the breedParams property as all parameters are now stored in model.params.
  • ⚠ addPrimitiveMoved from model.addPrimitive().
  • ⚠ removePrimitiveMoved from model.removePrimitive().
  • ⚠ addMoved from model.addParameter().
  • ⚠ addRenamed from Shocks.register().
  • ⚠ ShocksNow subclasses funcStore, which subclasses dict. The shocks property has been removed, replaced by accessing the object directly with the index, e.g. Shocks[name]. The number property has also been removed; use len(model.shocks) instead.
  • ⚠ clearMoved from model.clearEvents().
  • ⚠ addMoved from model.addEvent().
  • ⚠ CpanelRemoved the balloon property, which had been used for tooltips with PMW in the Tkinter frontend. Tooltips are now handled through the Tooltip class with no dependency.
    Removed the parent property as Cpanel now subclasses Tk. Code that formerly pointed to Cpanel.parent can now simply use Cpanel.
  • ⚠ ParamRenamed the obj parameter to per for clarity. obj is deprecated and will be removed in a future version.
    For per-breed and per-good parameters, the element property is now the containing Tkinter or Ipywidgets widget. The dict of individual widgets is now in the new elements property.
  • ⚠ MultiLevelDeprecated the dontStepAgents property. Use the cutStep() method instead.
  • ⚠ spatialReplaced the x, y, and square arguments with a single dim argument that can take an integer or a tuple.
  • ⚠ removeMoved from model.removeEvent().
  • ⚠ baseAgentAdded the overdraft static property to allow more control over cases where trades cannot be accomplished as written.
    Removed the currentShortage property as it had no clear meaning for some values of overdraft. This should be kept track of in individual models by comparing the input and return values of Agent.buy() and/or Agent.trade().
  • MPLVisualizationAdded the dim and pos properties.
  • GoodsIntroduced to replace the bare dict previously used to store goods.
  • expandableFrameChanged the open parameter to a settable bool that can also open and close the frame.
    Added the buttons property for placing action buttons in the title.
  • HooksIntroduced to replace the bare dict previously used to store hooks.
  • AgentsIntroduced to replace the bare dict previously used to store primitives.
  • groupIntroduced.
  • EventsIntroduced to replace the bare dict previously used to store events.
  • ParamsIntroduced to replace the bare dict previously used to store parameters.
  • darkenIntroduced.
  • cutStepIntroduced.
  • funcStoreIntroduced.
  • saveCSVIntroduced.
]]>
https://helipad.dev/2022/07/helipad-1-4/feed/ 0
Helipad 1.3 Improves Visualization Flexibility https://helipad.dev/2021/06/helipad-1-3/ https://helipad.dev/2021/06/helipad-1-3/#respond Sat, 19 Jun 2021 21:14:11 +0000 https://helipad.dev/?p=631 Helipad 1.3 is out now with a number of bug fixes and improvements to visualizations. Most importantly, you can mix and match time series and other visualizations, and you can display networks on spatial models now.

Network and Spatial Improvements

Most significantly, the spatial beta advances with the merging of the class formerly known as SpatialPlot into NetworkPlot, allowing the display of network connections on a patch grid. The spatial layout, which displays agent positions on the patch grid, is now available as a new network layout when a spatial model has been initialized. Other layouts can still be rotated through with the ‘l’ key to see the network structure without the patch geometry (for non-spatial models, the network visualizer will skip the spatial layout when rotating layouts). The new NetworkPlot class is fully backward-compatible with existing code for both model types.

A 5×1 patch grid with an undirected network shown on the agents.

This brings a number of benefits to both types of models, even when displaying a non-spatial network or a non-networked spatial model. First, for network models, node size can now be linked to an agent property, as had been possible in spatial models since 1.2. Network display can also be more extensively customized (e.g. labels can be toggled and customized) with the config() method previously used in the Spatial visualizer, and the config() method can now take a dict of key-value option pairs rather than calling it for every option.

For spatial models, the aspect ratio of the patches can now be customized, as in the above example, where the aspect is set to 2. And, of course, a network can be superimposed on agents as they move along the map now.

The NetworkNodeClick and SpatialAgentClick hooks have both been deprecated and replaced by a general agentClick hook, and spatialPatchClick with patchClick for consistency.

Time Series Plots Available in the Charts Visualizer

Time series plots alongside a spatial map in the Charts visualizer.
The time bar is scrubbed to t=66, which is indicated by the
vertical line in the time series plots.

When the extensible visualization API was introduced in Helipad 1.2, synchronic visualizations were handled by Charts, and diachronic visualizations with TimeSeries, despite the fact that both were able to be subdivided into plots (though slightly differently).

In Helipad 1.3, the TimeSeriesPlot class now subclasses ChartPlot, so time series can be mixed and matched with other synchronic visualizations like networks and bar charts.

Some functionality does differ from the TimeSeries visualizer to the Charts visualizer, since the former can treat time series as first-class citizens. First, TimeSeries stacks the plots, whereas Charts places them in squares. Second, the time scrubbing in Charts displays a vertical line to indicate the scrubbed time, so the entire series is always in view. Events continue to be displayed with a flash of the background, rather than vertical lines on the time series, as in the TimeSeries visualizer. Finally, automatic resolution change is not supported in the Charts visualizer.

Nevertheless, for models that require mixed visualizations, this added flexibility should open up new possibilities.

More Advanced Goods API

A new props argument on model.addGood() allows agents to hold various properties per good, making for more organized code in certain types of models. This is different from per-good parameters, which are set globally per-good, rather than per-agent per-good. For example an agent might have a reserve quantity, a minimum price, and a surplus for each good:

def maxReserve(breed): return random.randint(1,2000)
heli.addGood('sugar', '#FFFF00', props={'reserve': maxReserve, 'price': 1, 'surplus': False})
heli.addGood('water', '#00FFFF', props={'reserve': maxReserve, 'price': 1, 'surplus': False})

This gives agents 'reserve', 'price', and 'surplus' properties for each of the two goods, and sets the initial values in the same manner as the endowment argument (i.e. it can take a number, a tuple to sample from a normal distribution, or a function).

The quantity of the good held by the agent can be accessed normally with agent.stocks[good], so this new feature is fully backward-compatible with existing code. But other properties can now be accessed with a two-argument index. agent.stocks[good, 'reserve'], for example, will return the value of the agent’s 'reserve' property of the good. Agents’ good properties can be set this way too.

Other Improvements and Bug Fixes

  • An agent.transfer() method to move sub-agents in a multi-level model from one MultiLevel object to another.
  • The Charts visualizer now adds a checkgrid parameter allowing its plots to be individually toggled, similarly to TimeSeries.
  • Improved event handling at the plot level rather than at the visualizer level. Now ChartPlot subclasses can handle keypresses, mouse clicks, and item pick events without having to negotiate with the entire visualizer canvas (this will be mainly useful for those creating new visualizations by subclassing ChartPlot).
  • Patches are now created before other agent primitives in spatial models, so the agentPosition hook can reference patches.
  • Fixed a visual bug in some versions of Tkinter with global checkbox parameters.
  • Fixed a bug where some agents could be skipped when other agents have died that period.
  • Avoided a Matplotlib bug that was introduced in 3.4.0 and fixed in 3.4.2.

API Changes in Version 1.3

  • ⚠ agentClickIntroduced to replace both spatialAgentClick and networkNodeClick following the merge of the spatial and network visualizers.
  • ⚠ patchClickRenamed from spatialPatchClick following the merge of the spatial and network visualizers.
  • baseAgentAdded the fixed static property.
  • activeMoved from TimeSeriesPlot to ChartPlot as the former now subclasses the latter; now available to all ChartPlot visualizers.
  • TimeSeriesPlotNow subclasses ChartPlot for compatibility with the Charts visualizer.
  • MPLEventIntroduced.
  • transferIntroduced.
  • configAllow passing a dict of key-value pairs.
    Added the agentLabel and lockLayout parameters.
  • AgentsPlotMerged SpatialPlot into the Network visualizer to allow displaying network connections on a patch grid.
  • addAdded the props argument.
  • GoodReplaced the endowment property with the more general props. The value formerly contained in endowment can be accessed in good.props['quantity'].
  • SeriesMade the legend objects accessible with the legline and legtext properties, and added visibility controls with the visible property and the toggle() method.
  • addSeriesAdded the visible argument.
  • agentTransferIntroduced.
]]>
https://helipad.dev/2021/06/helipad-1-3/feed/ 0
Helipad 1.2 Introduces Extensible Visualization API and Events https://helipad.dev/2021/02/helipad-1-2/ https://helipad.dev/2021/02/helipad-1-2/#respond Wed, 10 Feb 2021 21:23:59 +0000 https://helipad.dev/?p=607 Helipad 1.2 is a significant update that, most importantly, features a new extensible visualization API along with several new visualizations. In addition, it includes Events, performance profiling, and full Jupyterlab support.

New Visualization API

The class formerly known as Graph is now called TimeSeries. In addition, visualizations other than TimeSeries may also be used. Charts, for example, is detailed below.

Accordingly, many visualization functions have been moved out of the model object and into the TimeSeries object, in order to allow other visualization classes to implement their own functionality more flexibly. Visualizations must now be registered explicitly, and can be interacted with in a new, more object-oriented API.

heli = Helipad()

#Old way, deprecated
heli.addPlot('plotarea', 'Plot Area')
heli.addSeries('plotarea', 'reportername', 'Series Name', '#FF0000')

#New way: object-oriented and explicit
from helipad.visualization import TimeSeries
viz = heli.useVisual(TimeSeries)
plot = viz.addPlot('plotarea', 'Plot Area')
plot.addSeries('reportername', 'Series Name', #FF0000')

This allows custom visualizations to specify their own methods and functionality. The methods of the included visualizations are documented in the function reference.

There are now three ways to create custom visualizations, depending on the amount of customization needed:

  1. Creating a new plot type for the Charts visualizer by subclassing ChartPlot, which allows the plot type to be displayed in a panel alongside other visualizations (there is a tutorial notebook for creating a 3D bar chart visualization this way),
  2. Creating an entirely new visualization window using Matplotlib by subclassing MPLVisualization (this will maintain compatibility with both Tkinter and Jupyter), or
  3. Creating an entirely new visualization window without Matplotlib by subclassing BaseVisualization (it is up to the code author to maintain compatibility, or not, with Tkinter or Jupyter).

Other miscellaneous visualization improvements:

  • Visualization windows no longer jump to the foreground on each refresh.
  • The visualization window no longer overflows the taskbar on Windows.

New Visualizations

In addition to the existing visualizations now under the TimeSeries class, which plots model data over time, there is a new extensible Charts visualization class, which plots model data at a single point in time. Charts can take a variety of plot types, including bar charts and network diagrams (pictured above), which can be extended by subclassing ChartPlot.

The bar chart is most similar to the existing plot-series paradigm, with a bar corresponding to a series, and BarChart.addBar() analogous to TimeSeriesPlot.addSeries(). In addition, like TimeSeries can plot percentiles when registered with Data.agentReporter(), the bar chart will display reporters with percentile subplots as bars with error bars. Finally, there is a new std parameter on Data.agentReporter(), which – like the percentiles argument – creates subseries, this time depicting ± some multiple of the standard deviation of the data series.

The NetworkPlot visualizer, which requires NetworkX, comes along with a number of improvements to Helipad’s network export function. The latter now stores edge weight and direction, as well as agent breed. The visualizer displays edge weight and direction, as well as coloring nodes by agent breed color. There is also a new networkNodeClick hook that receives an agent whose node was clicked on, for additional interactivity.

In addition, Charts has a time slider at the bottom, which allows the user to revisit past model states and scrub back over the model history. Like TimeSeries, Charts can be used both in the standalone Tkinter environment, as well as in a Jupyter notebook.

Spatial API Improvements

Coming along with the new visualizers, and building on the last version’s minimal spatial pre-alpha, Helipad’s support for spatial models has taken a leap.

Most significantly, model.spatial() now registers and returns a spatial visualizer, a ChartPlot subclass that can be displayed alongside other panels in the Charts visualizer. Patch color and agent size can both be set to reflect a Patch property or a stock of a good. In addition, there are hooks to receive clicked-on agents and patches, allowing – like the network plot – for additional interactivity with the visualization.

Second, agents may now take float positions, meaning they are not bound to the center of their patch. There is also a variety of new angle methods and properties, including an orientation property, as well as orientTo() that sets the agent’s orientation toward another agent or patch, and forward(), which moves the agent some number of steps forward in the direction of its orientation. See model.spatial() for details.

Finally, patches may now be accessed using model.patches[x,y] in addition to the usual model.patches[x][y].

With Helipad 1.2, spatial functionality enters beta, and every effort will be made to maintain backward-compatibility as new features are added.

Events

Helipad now supports events, which are triggers that fire when a certain user-defined condition is met. Events can be registered with a new @heli.event decorator, or with model.addEvent(). They can be singular, or repeat.

When triggered, an event stores the data output at that time, and sends a signal to the visualizer, which can display it as appropriate. TimeSeries, for example, draws a vertical line on the plots (see the image to the right), and Charts will flash the background. In the image to the right there are two events, marking the increase and leveling off of population.

Events now replace the ability to set the stopafter parameter to a function, including in parameter sweeps. Instead, stopafter can now be set to the name of an event, whose associated function serves the same purpose. In addition, parameter sweeps now return not only the final model data for each registered reporter, but also the data state at the firing of each registered event.

Performance Profiling

A small feature: setting model.timer=True will print speed data to the console at each refresh of the visualizer, dividing it between model run and visualization.

Period 20 : 21.57 periods/second ( 55.71 % model, 44.29 % visuals)
Period 40 : 27.84 periods/second ( 74.21 % model, 25.79 % visuals)
Period 60 : 29.39 periods/second ( 79.79 % model, 20.21 % visuals)

Miscellaneous

  • By switching the visualizers to use to the Matplotlib widget backend rather than nbagg, Helipad can now be run in Jupyter Lab in addition to the classic Notebook environment. Note that using Helipad in a Jupyter notebook either way now requires ipympl, and the widgets and matplotlib extensions must be installed in order to use it in Jupyter Lab. Since the recent release of Jupyter Lab 3.0, the widget installation process is much simpler.
  • Because of a simplification in storing parameter values, Helipad can now be used from the command prompt without initializing a Tkinter window.
  • The enabled state of the registered shocks can now be accessed and set as a pseudo-checkgrid parameter using model.param('shocks').
  • The updateEvery parameter has been renamed to refresh.

API Changes in Version 1.2

  • ⚠ launchVisualRenamed from launchPlots, which has been deprecated.
  • ⚠ paramSweepNow returns a list of Item objects rather than a tuple, in order to return more run data.
  • ⚠ ReporterAdded the collect() and clear() methods, and removed the series property, added the data property, and reorganized the children property.
  • ⚠ TimeSeriesRenamed from Graph to TimeSeries and now subclasses BaseVisualization. The plots property now contains all plots, and active plots are now in the activePlots property.
  • ⚠ visualLaunchRenamed from plotsLaunch, which has been deprecated.
  • ⚠ visualRefreshRenamed from graphUpdate, which has been deprecated.
  • agentReporterAdded the std argument.
  • ChartsIntroduced.
  • BarChartIntroduced.
  • AgentsPlotIntroduced.
  • ChartPlotIntroduced.
  • collectIntroduced.
  • spatialNow returns the NetworkPlot object.
    Agents can now take fractional coordinates.
    agent.moveTo() can now take a patch or an agent as a single argument.
    Added angle methods and properties orientation, orientTo(), and forward().
    agent.x and agent.y are now settable.
  • DataAdded the columns property.
  • addReporterNow returns a Reporter object.
  • useVisualIntroduced.
  • removePlotIntroduced in lieu of model.removePlot().
  • lightenAdded the factor parameter.
  • addPlotIntroduced in lieu of model.addPlot().
  • addNow returns the new Param object.
  • addSeriesIntroduced in lieu of model.addSeries().
  • clearIntroduced.
  • removeIntroduced.
  • EventIntroduced.
  • addIntroduced.
  • eventIntroduced.
  • HelipadIntroduced the timer property.
    The graph property has been renamed to visual.
  • removeIntroduced.
  • removePrimitiveCan now take a list, and returns a boolean indicating whether or not a primitive was in fact removed.
]]>
https://helipad.dev/2021/02/helipad-1-2/feed/ 0
Helipad 1.1 Adds Virtual Parameters, Improves Jupyter Flexibility, and More https://helipad.dev/2020/10/helipad-1-1/ https://helipad.dev/2020/10/helipad-1-1/#respond Wed, 21 Oct 2020 22:57:22 +0000 https://helipad.dev/?p=515 Helipad 1.1 is out today with a number of new possibilities and small quality-of-life improvements.

Virtual Parameters

The trio of add parameter functions – model.addParameter(), model.addGoodParam(), and model.addBreedParam(), can now accept setter and getter arguments to replace the parameter’s own internal handling.

One use of this might be to alias parameters. In this example, the user has an option of creating a square of a particular dimension or specifying an arbitrary height and width. In order to have 'x' and 'y' parameters available regardless of whether square==True, we can use the setter and getter arguments to alias the 'dimension' parameter.

if square:
	model.addParameter('dimension', 'Map Size', 'slider', dflt=x, opts={'low': 1, 'high': x, 'step': 1}, runtime=False)
	def dimget(name, model): return model.param('dimension')
	def dimset(val, name, model): model.param('dimension', val)
	model.addParameter('x', 'Map Width ', 'hidden', dflt=x, setter=dimset, getter=dimget)
	model.addParameter('y', 'Map Height', 'hidden', dflt=x, setter=dimset, getter=dimget)
else:
	model.addParameter('x', 'Map Width ', 'slider', dflt=x, opts={'low': 1, 'high': x, 'step': 1}, runtime=False)
	model.addParameter('y', 'Map Height', 'slider', dflt=y, opts={'low': 1, 'high': y, 'step': 1}, runtime=False)

Anything can go in the setter and getter functions, however, so you can set and get any model properties with the usual parameter types, no matter how complex. The agent population slider, for example, is now a virtual parameter that directly checks and modifies the agent population.

Improved Jupyter Flexibility

Helipad’s control panel is now a great deal more flexible in Jupyter notebooks. Two changes in particular bear mentioning.

First, the control panel can be drawn out of order with certain calls now. Where previously model.addPlot() and model.addParameter() would raise an error if the control panel had already been drawn, now the control panel will refresh automatically if a plot or a parameter is added after it’s drawn. Note that the behavior in Tkinter has not changed, and that these functions will still raise an error if called after the control panel has been drawn.

Connected to this, the Jupyter control panel can now be refreshed programmatically by calling Cpanel.__init__(model, redraw=True).

Second, the control panel can now be drawn multiple times in the same notebook, whereas before this would cause an error. Instead, when a new instance of the control panel is drawn, the old instance is now invalidated and control of the model transferred to the new cell.

These changes help accommodate the exploratory and nonlinear nature of writing a model in a Jupyter notebook.

Color API Improvements

First of all, the Colour dependency has been removed, and replaced with a bare-bones Color object for internal use. While this object will not typically be interacted with directly, it does come with a few user-facing improvements.

Most importantly, in functions that take a color – model.addGood(), model.addBreed(), and TimeSeriesPlot.addSeries(), the color argument is more flexible. Whereas previously it would only take a hex value, it can now take a hex value, a color name (see the Matplotlib documentation for the complete list of names), or an RGB tuple.

In order to support the use of color names, the use of hex values without the initial '#' is now deprecated. Existing code will still work, but will throw a warning. Per the deprecation policy, the ability to take prefix-less hex codes will be removed in Helipad 1.3.

Spatial Pre-Alpha

The methods and classes in the spatial sample model have been moved into core, along with a new function model.spatial(), which initializes a network of patches and adds properties and methods to all agents for location and movement. A new sample model of sheep and grass using the spatial capability is also included.

This is a preview and is not API-stable. There is no visualization capability yet, and no promise of backward-compatibility until the feature is finalized. Nevertheless, it should function as a solid foundation for spatial models.

Other Improvements

  • The endowment argument of model.addGood() can now take a two-item tuple, a low and a high value, to endow agents with a random amount of the good between these two values.
  • The automatically generated ‘agents_[primitive]‘ parameter, with the population of agents of each primitive, has been renamed to the clearer ‘num_[primitive]‘. A model which does not create any new primitives, for example, can now set and get the population using ‘num_agents‘. The use of the agents_ prefix is now deprecated and will be removed in Helipad 1.3.
  • Because the coefficients of a CES utility function become the exponents of a Cobb-Douglass utility function when the elasticity of substitution equals one, the exponents of the CobbDouglas object were previously accessed using the coeffs property inherited from the parent CES class. These can now be accessed more intuitively using the new CobbDouglas.exponents property, which aliases the coeffs property.

API Changes in Version 1.1

  • ⚠ addThe endowment argument can take a tuple for a random endowment.
    The color argument can now take an RGB tuple or a color name string. Note that hex strings now take an initial '#'. The use of bare hex strings is deprecated and will be removed in a future version.
  • ⚠ addBreedThe color argument can now take an RGB tuple or a color name string. Note that hex strings now take an initial '#'. The use of bare hex strings is deprecated and will be removed in a future version.
  • ColorIntroduced in lieu of the colour library.
  • initializeFunction signature changed to make it a parameter setter function rather than a GUI callback.
  • addAdded the setter and getter arguments to support virtual parameters.
  • spatialIntroduced.
]]>
https://helipad.dev/2020/10/helipad-1-1/feed/ 0
Helipad 1.0 Runs in Jupyter Notebooks, and Much More https://helipad.dev/2020/08/helipad-1-0/ https://helipad.dev/2020/08/helipad-1-0/#respond Thu, 06 Aug 2020 03:52:50 +0000 https://helipad.dev/?p=491 Helipad 1.0 has just launched with a plethora of improvements. Most importantly: you can now run Helipad models in Jupyter notebooks.

Jupyter Integration

Jupyter notebooks are interactive documents into which you can embed Python code to run in-browser. They’re popular for sharing scientific code because putting code in a document can be much more readable than putting comments in code.

Helipad can now run a full-featured instance inside a Jupyter notebook, with the same control panel experience and interactive plotting. Anything you can do with the Tkinter frontend, you can now do in the Jupyter frontend as well, with no* changes to your code. (*except that you’ll need to launch the plots explicitly with a heli.launchVisual() line at the end)

To try out the new Jupyter frontend,

  1. Download one of the sample notebooks
  2. Install Jupyter and Ipywidgets using pip install jupyterlab and pip install ipywidgets
  3. Launch the notebook from your terminal using jupyter notebook /path/to/notebook.ipynb

Because the code can be written and run in-browser, this should flatten the learning curve for writing a Helipad model and increase the shareability of model code.

New Decorators

The most significant API update is a set of new decorators to add hooks and reporters. Previously, it was necessary to define a function and then register it using model.addHook(). This entailed a lot of repetition.

Starting with Helipad 1.0, you can now register hooks using a decorator syntax. Just name your function according to the hook, and add @heli.hook at the top.

from helipad import Helipad
heli = Helipad()

@heli.hook
def modelStep(model, stage):
    pass

You can also use @heli.hook('modelStep') if you want to hook a function of any name to the modelStep hook, for example.

There are also decorators for reporters and button shocks. Though most reporters will still be generated with the data methods, if you’re defining your own reporter function, you can register it with the @heli.reporter decorator. Similarly, you can add buttons easily to the control panel with @heli.button.

API Stability

With the release of Helipad 1.0, every effort will be made to maintain backward-compatibility. Documented functions and properties will not change before six months or two 0.1 releases after the first release in which they are deprecated, whichever is longer. Undocumented functions and properties can change without notice.

Other Improvements

  • Plotting is now completely independent of the control panel. So you can launch the traditional way with model.launchCpanel(), jump straight into plotting with model.launchVisual(), or go completely GUI-less with model.start() (In the latter two cases you’ll have to set parameter values, including any data post-processing, in code).
  • Param objects now allow you to enable and disable the GUI element.
  • Model control is handled in the model object now, rather than the Cpanel object. If you need to control the model with code, use model.start(), model.stop(), and model.terminate().
  • New parameter types checkentry and checkgrid can be registered with model.addParameter().
  • Sliders can be registered with discrete and arbitrary values by passing a list of values to the opts argument of model.addParameter().
  • The CSV and stop-after boxes, along with the refresh rate slider and the plot list, are now proper parameters and can be accessed and set using model.param() under the names 'csv', 'stopafter', 'updateEvery', and 'plots', respectively.
  • The stopafter parameter can be set to a function rather than a number, in order to stop the model after an arbitrary condition is fulfilled. This can also be used in parameter sweeps.
  • Plots can be activated and deactivated from code with the new Plot.active() method.

The full list of API changes is below.

API Changes in Version 1.0

  • ⚠ HelipadRemoved model.defaultPlots. Select plots programmatically with the selected argument of model.addPlot(), or after the fact with TimeSeriesPlot.active().
    Moved Cpanel.graph and Cpanel.running to the model object.
    Model control (the start(), stop(), and terminate() methods) is handled here rather than in the Cpanel object.
    Removed the buttons property. The addButton() method now aliases Shocks.register().
  • ⚠ addButtonPass the model object to the button function, and move the display from the top to the shocks section.
  • ⚠ paramSweepRemoved the t parameter. Use model.param('stopafter') to set a time limit or a stop condition.
  • ⚠ CpanelChanged name to Cpanel from GUI.
    Moved the graph and running properties to the model object, and the lastUpdate property to the Graph object.
    Removed the headless parameter and property. To run the model headless, run model.launchPlots() without running model.launchCpanel().
    The stopafter, updateEvery, csv, and checks properties, which formerly stored Tkinter widgets relating to configuration, have been removed. Their values can be accessed through parameters of the same name with model.param() except checks, which can now be accessed with model.param('plots').
    Moved model control methods run(), pause(), terminate(), and preparePlots() to model.start(), model.stop(), model.terminate(), and model.launchPlots(), respectively.
    With the plot list being a parameter now, the CpanelAbovePlotlist hook has been removed.
  • ⚠ launchCpanelRenamed from model.launchGUI, and removed the headless parameter. To run the model headless, run model.launchPlots() without calling this function.
  • ⚠ launchVisualMoved from Cpanel.preparePlots.
  • ⚠ CpanelAboveItemParamsName changed from GUIAboveItemParams.
  • ⚠ CpanelPreLaunchName changed from GUIPreLaunch.
  • ⚠ CpanelPostInitName changed from GUIPostInit.
  • ⚠ CpanelTopName changed from GUITop.
  • ⚠ CpanelBottomName changed from GUIBottom.
  • ⚠ CpanelAboveShocksName changed from GUIAboveShocks.
  • ⚠ CpanelAboveParamsName changed from GUIAboveParams.
  • ⚠ modelStopTakes the model object rather than the GUI object as the first argument.
  • ⚠ terminateTakes the model object rather than the GUI object as the first argument.
  • ⚠ GUICloseNever executes in a Jupyter environment.
  • launchCpanelInterrupts the 'Run All' sequence in a Jupyter environment.
  • @reporterIntroduced.
  • enableIntroduced.
  • disableIntroduced.
  • disabledIntroduced.
  • @buttonIntroduced.
  • @hookIntroduced.
  • genDecoratorIntroduced.
  • startIntroduced as part of the transfer of model control functions from GUI to the model object.
  • ParamAdded the defaultVal property, and split the parameter types into subclasses.
  • addAdded support for checkgrid, checkentry, and logslider parameters.
  • checkEntryAdded the command argument and callback parameters to enable callback functions.
  • disabledMade the second parameter optional to allow the entire checkGrid to be enabled or disabled at once.
  • addCheckNow returns the textCheck widget.
  • addAdded the prioritize argument.
  • TimeSeriesAdded the lastUpdate property, formerly from the GUI object.
  • logSliderWith the log slider now available for use in user-defined parameters, the Tkinter class now has a complement of methods: set, get, enable, disable, and disabled.
  • TimeSeriesPlotAdded the check and selected properties and the active() method.
  • activeIntroduced in the TimeSeriesPlot class.
  • visualLaunchIntroduced.
]]>
https://helipad.dev/2020/08/helipad-1-0/feed/ 0
Helipad 0.7 has Stackplots and Parameter Sweeps https://helipad.dev/2020/06/helipad-0-7/ https://helipad.dev/2020/06/helipad-0-7/#respond Thu, 25 Jun 2020 21:08:33 +0000 https://helipad.dev/?p=475 Helipad 0.7 is here with two big features: stackplots, and parameter sweeps.

Stackplots

If you’ve wanted to plot things where the total matters, or maybe where the values add up to a constant total and you’re interested in the relative proportions, stackplots can improve the visualization.

The Deme Selection sample model introduced in Helipad 0.6 is a good example (and see that page for the “before” screenshot): the top plot depicts the proportion of altruistic versus selfish phenotypes. But the plots are mirror images of one another. A stackplot eliminates the redundancy and makes it easier to scan the model output.

To turn a plot into a stackplot, just add a stack=True argument when calling model.addPlot().

Parameter Sweeps

A parameter sweep is a common way to exploring the sensitivity of an agent-based model to its parameter values by running the model repeatedly and systematically varying one or more parameters. In NetLogo, for example, this is called BehaviorSpace.

This is now possible with Helipad’s new paramSweep function. Because possible values of any parameter are nailed down when instantiated with the addParameter function, even for numerical variables (because the min, the max, and the step are set for sliders), all paramSweep needs to know is the variable(s) to sweep and how long to run each instance. The former can sweep n-dimensional parameter spaces (i.e. every combination of possible values from n different parameters), and the latter can specify either a fixed time, or a function with arbitrary stop conditions, for example if you’re trying to see if the variable affects how long it takes to get to equilibrium.

Sweeping hundreds or thousands of parameter combinations is a time-consuming task, so to make it as fast as possible, the parameter sweep bypasses the GUI and returns the results of each run as a Pandas dataframe, whose columns can optionally be narrowed just to the data of interest.

Other Changes

Helipad 0.7 has a new createNetwork function that automatically generates an undirected and unweighted network of a specific density among agents. Helipad’s support for network types means that multiple distinct networks can be created this way, even over the same agents.

More significantly, to support the new parameter sweep functionality and to simplify the internals, the way parameters are handled internally has changed. The upshot is two things:

  1. More consistency in how callbacks and updating parameters are handled. For example, updating a parameter value in code will always update the parameter value in the GUI, where previously this was not true for sliders due to a Tkinter inconsistency.
  2. A new pattern for identifying parameters to functions.

This second feature is backward-incompatible and entails a few function removals and signature changes. First, functions that need to identify a parameter (for example model.param, model.paramSweep, and Shocks.register) now all do so with a single tuple-argument pattern, rather than the ad hoc list of optional arguments like obj, prim, breed, good, and so on.

The new parameter identification pattern looks like this:

  • A global parameter can be identified using a string or a one-element tuple. model.param('pSmooth') retrieves the value of the global pSmooth parameter.
  • The parameter values for all items – for example a per-breed or a per-good parameter – can be retrieved using a two-element tuple. model.param(('productivity', 'good')) retrieves a dict of the productivity parameter values for all goods. Note that parameters cannot be set this way.
  • The parameter value for a particular item of a per-breed or per-good tuple can be referred to using a three-element tuple. model.param(('demand', 'breed', 'hobbit'), 50) sets the demand parameter for the hobbit breed to 50.
  • Finally, because breeds apply only to specific agent primitives, when there are multiple primitives, the relevant primitive is specified using a fourth element of the tuple (this is optional when there is only one primitive). The previous example could also be specified model.param(('demand', 'breed', 'hobbit', 'agent), 50).
  • The second case can also be achieved in the event of multiple primitives by putting None as the third element. model.param(('demand', 'breed', None, 'agent)) returns a dict of the demand breed parameter values for all breeds of the agent primitive.

This simplifies the internals a good bit, and standardizes the parameter interface across several different functions. It also obviates the goodParameter and breedParameter functions, which have been removed. Your code should replace them with the new and more powerful param function.

The full list of API changes follows.

API Changes in Version 0.7

  • ⚠ TimeSeriesRemoved Graph.graph (the list of Matplotlib AxesSubplot objects) and Graph.series (the list of Matplotlib Line objects). These are now kept track of in the Plot objects stored in Graph.plots.
  • ⚠ HelipadRemoved the updateVar, breedParam, and goodParam methods. The latter two are replaced by a more flexible param method that can take parameter ID tuples now.
  • ⚠ CpanelRemoved the sliders property. Parameter widgets are now stored in Param.element.
  • ⚠ ShockReplaced the var, paramType, and prim properties, which stored attributes of the parameter, with the param property, which stores the parameter object itself.
  • ⚠ addReplaced the var, paramType, and prim arguments with the param argument, a standard parameter identification tuple or string.
  • ⚠ paramReplaced the name and several undocumented arguments with the param argument, to increase flexibility and accommodate the new parameter identification pattern.
  • ⚠ GUICloseRenamed GUIPostLaunch to GUIClose to more accurately reflect the hook's place in the flow, and passed the model instead of the GUI object.
  • TimeSeriesPlotKeep track of the Matplotlib AxesSubplot object here rather than in a separate list in Graph.
  • SeriesKeep track of the Matplotlib Line object here rather than in a separate list in Graph, and the output series here rather than in the Line object.
  • addReturns a Good object.
  • addBreedReturns a Breed object.
  • createNetworkIntroduced.
  • ParamAdded the obj, range, and element properties, and the get, set, reset, and addKey methods.
  • paramSweepIntroduced.
]]>
https://helipad.dev/2020/06/helipad-0-7/feed/ 0
Helipad 0.6 supports multi-level modeling https://helipad.dev/2020/05/helipad-0-6/ https://helipad.dev/2020/05/helipad-0-6/#respond Sat, 09 May 2020 17:35:55 +0000 https://helipad.dev/?p=451 Helipad 0.6 supports multi-level agent-based modeling, where the agents at one level are themselves full models. Simply register a primitive with the new Helipad.MultiLevel object, which inherits properties from both the baseAgent and Helipad classes.

To demonstrate the new feature, a new sample model of group selection for altruism is included, based on Bowles and Gintis (2011, ch.7): selfish agents are selected for within demes, but altruistic agents are selected in competition between demes. The demes are instantiated with the new MultiLevel object, and contain Agents of their own.

Notice also in this screenshot the window titles. One minor nicety introduced in 0.6 is the ability to name the model by setting model.name, which allows the GUI’s window titles to be customized.

One important backward-incompatible change is that Agent.goods has been renamed to Agent.stocks. Because MultiLevel inherits from both Helipad and baseAgent, the fact that model.goods and Agent.goods were doing different things was causing problems. If you were using the goods API, be sure to update the property name in your code.

Finally, some internal data structures have been simplified and rearchitected in order to provide more flexibility for future functionality. If you were accessing parameter, primitive, or shock data directly (which is not recommended), be aware that the structure has been changed.

A complete list of API changes is below.

API Changes in Version 0.6

  • ⚠ ShocksAdded the Shock class as a property, and removed the Shocks.do() method. Instead of Shocks.do(name), use Shocks[name].do(model).
  • ⚠ baseAgentagent.goods renamed to agent.stocks to avoid a conflict with model.goods in multi-level models.
  • ⚠ ParamConverted to an Item object rather than a dict
  • ⚠ PrimitiveConverted to an Item object rather than a dict
  • ⚠ ShockConverted to an Item subclass rather than a dict, and added the .do() method to replace Shocks.do().
  • Helipadmodel.name introduced
  • removePrimitiveIntroduced.
  • agentReporterDefault for prim argument changed from 'agent' to None
  • summaryDefault for prim argument changed from 'agent' to None
  • MultiLevelIntroduced.
]]>
https://helipad.dev/2020/05/helipad-0-6/feed/ 0